Pg put line: примеры (PHP)
pg_put_line(PgSql\Connection $connection, string $data): boolФункция pg_put_line отправляет строку данных на сервер PostgreSQL в режиме копирования. Она применяется при выполнении операций COPY FROM или COPY TO для передачи данных построчно, что эффективно для массовой загрузки или выгрузки информации.
- connection – ресурс соединения с базой данных PostgreSQL.
- data – строка для отправки на сервер. Должна заканчиваться символом новой строки, который добавляется автоматически, если отсутствует.
Функция возвращает true после успешной отправки строки или false при возникновении ошибки.
<?
$conn = pg_connect("host=localhost dbname=test");
pg_query($conn, "COPY mytable FROM STDIN");
pg_put_line($conn, "1\tЗначение 1\n");
pg_put_line($conn, "2\tЗначение 2\n");
pg_put_line($conn, "3\tЗначение 3\n");
pg_put_line($conn, "\\.\n");
pg_end_copy($conn);
?>Результат: данные успешно загружены в таблицу mytable.
<?
pg_query($conn, "COPY logs FROM STDIN");
// Символ новой строки не добавлен в строку
pg_put_line($conn, "2023-10-01\tОшибка подключения");
// Функция автоматически добавит \n
pg_put_line($conn, "\\.");
pg_end_copy($conn);
?>Результат: строка '2023-10-01\tОшибка подключения\n' отправлена на сервер.
Для работы с данными PostgreSQL доступны несколько функций:
- pg_copy_from – загружает массив данных в таблицу с помощью команды
COPY. Позволяет передать все данные одним вызовом. - pg_copy_to – выгружает данные из таблицы в массив. Обе функции работают с массивами, что удобно для небольших объемов информации.
- pg_query с
INSERT– подходит для единичных вставок, но менее эффективен при массовой загрузке.
Функция pg_put_line применяется при потоковой передаче больших объемов данных, когда их нельзя или неэффективно хранить в памяти целиком.
import psycopg2
conn = psycopg2.connect("dbname=test")
cursor = conn.cursor()
cursor.copy_from(open('data.csv'), 'mytable', sep='\t')
conn.commit()Результат: данные из файла загружены в таблицу.
const { Client } = require('pg');
const client = new Client();
await client.connect();
const stream = client.query(copyFrom('COPY mytable FROM STDIN'));
stream.write('1\tЗначение 1\n');
stream.write('2\tЗначение 2\n');
stream.end();
await client.end();Результат: строки переданы в таблицу.
Pg put line в MySQL
В MySQL аналогичная операция выполняется командой LOAD DATA INFILE:
LOAD DATA INFILE 'data.csv' INTO TABLE mytable
FIELDS TERMINATED BY '\t' LINES TERMINATED BY '\n';Результат: данные из файла загружены в таблицу.
Основное отличие pg_put_line – возможность потоковой передачи данных напрямую из PHP без промежуточных файлов.
<?
pg_query($conn, "COPY table FROM STDIN");
pg_put_line($conn, "1\tДанные\n");
// Забыли добавить строку с \\.\n
pg_end_copy($conn);
?>Результат: сервер ожидает продолжения данных, операция зависает.
<?
pg_query($conn, "COPY table FROM STDIN");
// Отсутствует разделитель между полями
pg_put_line($conn, "1Значение\n");
pg_put_line($conn, "\\.\n");
pg_end_copy($conn);
?>Результат: ошибка PostgreSQL 'extra data after last expected column'.
<?
pg_query($conn, "COPY table FROM STDIN");
pg_put_line($conn, "1\tДанные\n");
pg_put_line($conn, "\\.\n");
pg_end_copy($conn);
// Попытка отправить данные после завершения
pg_put_line($conn, "2\tЕще данные\n");
?>Результат: предупреждение 'pg_put_line(): Send of query failed'.
В PHP 8.1 функция pg_put_line стала возвращать значение типа bool вместо int. Ранее успешное выполнение возвращало 1, теперь – true.
Начиная с PHP 8.0, при передаче некорректного типа аргумента возникает исключение TypeError. В более ранних версиях выдавалось предупреждение.
<?
// PHP 8.0 и выше
pg_put_line([], "data\n");
?>Результат: TypeError: pg_put_line(): argument #1 ($connection) must be of type PgSql\Connection, array given.
<?
$conn = pg_connect("host=localhost dbname=test");
pg_query($conn, "COPY products FROM STDIN WITH (FORMAT CSV, HEADER false)");
$handle = fopen('large_products.csv', 'r');
if ($handle) {
while (($line = fgets($handle)) !== false) {
pg_put_line($conn, $line);
}
fclose($handle);
}
pg_put_line($conn, "\\.\n");
pg_end_copy($conn);
?>Результат: содержимое файла large_products.csv загружено в таблицу products.
<?
pg_query($conn, "COPY test FROM STDIN");
// Данные содержат табуляцию и обратную косую черту
$data = "1\tЗначение с \\ обратной чертой\n";
pg_put_line($conn, $data);
// Экранированная обратная косая черта передается как один символ
pg_put_line($conn, "2\tЕще \\\\ данные\n");
pg_put_line($conn, "\\.\n");
pg_end_copy($conn);
?>Результат: в таблице test будут строки: '1', 'Значение с \\ обратной чертой' и '2', 'Еще \\ данные'.
<?
function generate_data($rows) {
for ($i = 0; $i < $rows; $i++) {
yield $i . "\t" . md5($i) . "\t" . microtime(true) . "\n";
}
}
pg_query($conn, "COPY hash_table FROM STDIN");
foreach (generate_data(100000) as $line) {
pg_put_line($conn, $line);
}
pg_put_line($conn, "\\.\n");
pg_end_copy($conn);
?>Результат: 100 тысяч строк сгенерированных данных загружены в таблицу hash_table без высокого потребления памяти.