php postgresql pdo copy from stdin

pdo php postgresql sqlbulkcopy

문제

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

PDO가이 쿼리를 실행하는 방법은 무엇입니까?

최신 정보:

문제는 PDO 드라이버가이 쿼리를 명령문으로 실행한다는 것입니다.
예를 들어 pgAdmin에 붙여 넣으면 오류가 발생합니다.
psql 에서 실행해야합니다.

C:\Users\User>psql -e -h localhost -U postgres db_name
psql (9.1.2)
db_name=# COPY table_name ( field1, field2, field3) FROM STDIN CSV;
COPY table_name ( field1, field2, field3) FROM STDIN CSV;
Enter data to be copied followed by a newline.
End with a backslash and a period on a line by itself.
>> 1,2,"q w"
>> 3,4,"a s"
>> 5,6,d
>> \.

수락 된 답변

이 책 덕분에

여기에 제시된 기능은 보안 제한을 우회하는 데 이유가 있습니다. 함수는 엄격한 화이트리스트 조건에 대해 제공되는 파일 경로와 테이블을 확인해야합니다. 이 예제는 입력을 올바르게 인용하지 않기 때문에 SQL 인젝션에도 열려 있습니다.

COPY 명령을 수행하는 함수 생성

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;

PHP에서 실행

$dbh->exec('SELECT copy_from_csv_ignoring_security(...)');

===== 위의 버전> = 9.1.7 트릭이 작동하지 않는 경우. =====

해결책:

이 스크립트를 실행하는 사용자의 홈 디렉토리에 .pgpass 파일 (비밀번호 프롬프트 사용 안 함)을 만듭니다.

#.pgpass contents (chmod 600 - requred)    
host:port:db_name:user_name:password

메타 명령 을 실행하는 PHP 함수를 생성합니다.

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);

인기 답변

입력 줄을 csv 파일에 input.csv 라고 input.csv 다음 다음을 시도하십시오.

<?php
$dbh = new PDO($dsn,$username,$pw);

$num_inserted=$dbh->exec("\copy table_name(field1,field2,field3) from /path/to/input.csv");

if($num_inserted===false)
{
  die("Unable to insert rows into table_name from input.csv\n");
}

echo("Inserted $num_inserted rows.\n");
?>


아래 라이선스: CC-BY-SA with attribution
와 제휴하지 않음 Stack Overflow
이 KB는 합법적입니까? 예, 이유를 알아보십시오.
아래 라이선스: CC-BY-SA with attribution
와 제휴하지 않음 Stack Overflow
이 KB는 합법적입니까? 예, 이유를 알아보십시오.