来自stdin的php postgresql pdo副本

来自stdin的php postgresql pdo副本,php,postgresql,pdo,sqlbulkcopy,Php,Postgresql,Pdo,Sqlbulkcopy,如何通过PDO执行此查询 更新: 问题是PDO驱动程序将此查询作为语句执行。 例如,如果将其粘贴到pgAdmin中,则会抛出一个错误。 我需要在psql中执行它: C:\Users\User>psql-e-h localhost-U postgres db\U name psql(9.1.2) db_name=#从标准文本CSV复制表_name(字段1、字段2、字段3); 从STDIN CSV复制表_名称(字段1、字段2、字段3); 输入要复制的数据,后跟换行符。 以反斜杠和句点结束。 >>1,

如何通过PDO执行此查询

更新: 问题是PDO驱动程序将此查询作为语句执行。
例如,如果将其粘贴到pgAdmin中,则会抛出一个错误。
我需要在
psql
中执行它:

C:\Users\User>psql-e-h localhost-U postgres db\U name
psql(9.1.2)
db_name=#从标准文本CSV复制表_name(字段1、字段2、字段3);
从STDIN CSV复制表_名称(字段1、字段2、字段3);
输入要复制的数据,后跟换行符。
以反斜杠和句点结束。
>>1,2,“q w”
>>3,4,“a s”
>>5,6,d
>> \.

只需将输入行放入csv文件,比如说
input.csv
,然后尝试以下操作:

COPY table_name ( field1, field2, field3) FROM STDIN CSV;
1,2,"q w"
3,4,"a s"
5,6,d
\.

多亏了

请注意,此处提供的函数有效地绕过了安全限制,这些限制是有原因的。您的函数应该根据严格的白名单条件检查提供的文件路径和表。此示例也可以接受SQL注入,因为它没有正确引用其输入。

创建执行
COPY
命令的函数 从PHP执行 ====如果版本>=9.1.7以上的技巧不起作用 解决方案:

在运行此脚本的用户的主目录中创建文件(避免密码提示)

$dbh->exec('SELECT copy_from_csv_ignoring_security(...)');
创建php函数,该函数执行

函数executeMetaCommand($dbUser、$dbName、$dbPort、$command)
{    
$command=sprintf(

“psql-U%s-p%s-d%s-f-@wildplasser转义符(在我的例子中是双引号)需要count words>1的字符串。
”-默认转义符我刚刚删除了注释。似乎是引号(或缺少引号)被忽略。好。错误:必须是超级用户才能复制到文件或从文件复制提示:任何人都可以复制到标准输出或标准输入。psql的\COPY命令也适用于任何奇怪的人…我可以使用
psql
在没有超级用户访问的情况下复制数据。版本:9.1用户和数据库创建人:创建角色DB\u name NOSUPERUSER NOCREATEDB nocreatenOINHERIT NOLOGIN;创建角色db_user NOSUPERUSER NOCREATEDB NOCREATEROLE NOINHERIT登录加密密码“PASSWORD”;将db_名称授予db_用户;创建数据库db_名称,所有者=db_user;从public中撤销数据库db_名称上的所有内容;@cetver-编辑已完成。您应该能够使用
exec
方法传递
\copy
命令。对于任何想知道为什么这不起作用的人,
\copy
是命令行客户机
psql
特有的命令,不能在与服务器的其他连接上执行。我不确定为什么这不是语法错误,但从报告的消息来看,我猜它被解释为SQL
copy
语句,这不是一回事。请注意,从安全角度来看,这里编写的pl/pgSQL函数是一个非常糟糕的主意-它允许任何用户从命令运行任何
复制。Postgres故意限制这一点,以便您无法访问服务器配置的随机位,其想法是编写一个特权函数此函数也对SQL注入开放,因为当它从参数构造动态SQL时,它没有使用
quote_literal
quote_ident
。同意,但2选项是安全的。我冒昧地编辑了您的答案,以说明此函数有多不安全,因为我害怕人们将在未意识到的情况下复制并粘贴它。有关如何正确操作的讨论,请参阅我的博客:
CREATE OR REPLACE FUNCTION copy_from_csv_ignoring_security(table_name text, table_fieds text, file_path text, oids boolean DEFAULT false, header boolean DEFAULT false, delimeter text DEFAULT ','::text, "null" text DEFAULT ''::text, quote text DEFAULT '"'::text, escape text DEFAULT '"'::text, force_not_null text DEFAULT ''::text)
  RETURNS void AS
$BODY$

declare statement text;
begin

statement := 'COPY ' || table_name || ' (' || table_fieds || ') ' || 'FROM ''' || file_path || ''' WITH ';
IF oids THEN
 statement := statement || 'OIDS ';
end if;
statement := statement || 'DELIMITER ''' || delimeter || ''' ';
statement := statement || 'NULL ''' || "null" || ''' CSV ';
IF header THEN
 statement := statement || 'HEADER ';
end if;
statement := statement || 'QUOTE ''' || "quote" || ''' ';
statement := statement || 'ESCAPE ''' || "escape" || ''' ';
IF force_not_null <> '' THEN
statement := statement || 'FORCE NOT NULL ''' || force_not_null || ''' ';
end if;
execute statement;
end;
$BODY$
  LANGUAGE plpgsql VOLATILE SECURITY DEFINER
  COST 100;
revoke all on function copy_from_csv_ignoring_security(text, text, text, boolean, boolean, text, text, text, text, text) from public;
grant execute on function copy_from_csv_ignoring_security(text, text, text, boolean, boolean, text, text, text, text, text) to db_user;
$dbh->exec('SELECT copy_from_csv_ignoring_security(...)');
#.pgpass contents (chmod 600 - requred)    
host:port:db_name:user_name:password
function executeMetaCommand($dbUser, $dbName, $dbPort, $command)
{    
    $command = sprintf(
        "psql -U %s -p %s -d %s -f - <<EOT\n%s\nEOT\n",
        $dbUser, $dbPort, $dbName, $command
    );
    $streams = array(
        array('pipe', 'r'),// stdin
        array('pipe', 'w'),// stdout
        array('pipe', 'w') // stderr
    );
    $process = proc_open($command, $streams, $pipes);
    if (!is_resource($process)) {
        throw new Exception("Cannot open process:\n$command");
    } else {
        list(, $stdout, $stderr) = $pipes;
        $error = stream_get_contents($stderr);
        fclose($stderr);
        if (strlen($error) > 0) {
            throw new Exception("Process error:\n$error");
        } else {
            $output = stream_get_contents($stdout);
            fclose($stdout);
            $returnCode = proc_close($process);
            if ($returnCode === -1) {
                throw new Exception("Process was completed incorrectly:\n$output");
            } else {
                return array(
                    $returnCode,
                    $output
                );
            }
        }
    }
}

//usage:
$command = sprintf("\\copy table(field1, field2) FROM '%s' WITH CSV", $filePath);
executeMetaCommand('postgres', 'test_db', '5432', $command);