来自stdin的php postgresql pdo副本
如何通过PDO执行此查询 更新: 问题是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,
例如,如果将其粘贴到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
特有的命令,不能在与服务器的其他连接上执行。我不确定为什么这不是语法错误,但从报告的消息来看,我猜它被解释为SQLcopy
语句,这不是一回事。请注意,从安全角度来看,这里编写的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);