Pg prepare: примеры (PHP)

Использование pg_prepare для запросов к PostgreSQL
Раздел: Базы данных (PostgreSQL)
pg_prepare(PgSql\Connection $connection, string $stmtname, string $query): PgSql\Result|false
Описание функции pg_prepare

Функция pg_prepare в PHP используется для создания подготовленного SQL-запроса на соединении с базой данных PostgreSQL. Подготовленные запросы повышают производительность и безопасность при многократном выполнении одного и того же запроса с разными параметрами.

Функция применяется, когда необходимо выполнить один и тот же запрос много раз с разными значениями. Подготовленный запрос компилируется один раз, что снижает нагрузку на сервер БД и защищает от SQL-инъекций.

Аргументы функции
  • connection (ресурс PostgreSQL): Обязательный параметр. Ресурс подключения к базе данных PostgreSQL, возвращаемый функциями pg_connect или pg_pconnect.
  • statementname (строка): Имя для подготовленного запроса. Должно быть уникальным в пределах соединения. Можно использовать пустую строку, чтобы создать анонимный подготовленный запрос.
  • query (строка): SQL-запрос, который необходимо подготовить. В запросе могут использоваться плейсхолдеры $1, $2 и т.д., которые заменяются фактическими значениями при выполнении.

Функция возвращает ресурс результата подготовки при успехе или false в случае ошибки.

Короткие примеры использования
Подготовка запроса с плейсхолдерами
$conn = pg_connect('host=localhost dbname=test user=postgres');
$result = pg_prepare($conn, 'user_query', 'SELECT * FROM users WHERE id = $1');
var_dump($result);
object(PgSql\Result)#2 (0) {
}
Подготовка анонимного запроса
$conn = pg_connect('host=localhost dbname=test user=postgres');
$result = pg_prepare($conn, '', 'INSERT INTO logs(message) VALUES ($1)');
var_dump($result);
object(PgSql\Result)#2 (0) {
}
Выполнение подготовленного запроса
$conn = pg_connect('host=localhost dbname=test user=postgres');
pg_prepare($conn, 'get_user', 'SELECT name, email FROM users WHERE age > $1');
$res = pg_execute($conn, 'get_user', [25]);
while ($row = pg_fetch_assoc($res)) {
    print_r($row);
}
Array
(
    [name] => Иван
    [email] => ivan@example.com
)
Array
(
    [name] => Мария
    [email] => maria@example.com
)
Похожие функции в PHP
  • pg_query_params: Выполняет SQL-запрос с параметрами, но без явного создания именованного подготовленного запроса. Эта функция полезна для однократного выполнения запроса с параметрами. Она автоматически создает и использует анонимный подготовленный запрос.
  • pg_send_prepare и pg_send_execute: Асинхронные версии для подготовки и выполнения запросов. Применяются, когда нужно избежать блокировки скрипта на время выполнения запроса.

pg_prepare предпочтительнее использовать, когда один запрос выполняется много раз в рамках одного соединения. pg_query_params удобнее для однократных запросов.

Аналоги в других языках
Python (библиотека psycopg2)
import psycopg2
conn = psycopg2.connect('dbname=test user=postgres')
cur = conn.cursor()
cur.execute('PREPARE userplan AS SELECT * FROM users WHERE id = $1')
cur.execute('EXECUTE userplan (%s)', [5])
print(cur.fetchall())
JavaScript (библиотека node-postgres)
const { Client } = require('pg');
const client = new Client();
await client.connect();
const query = {
    name: 'fetch-user',
    text: 'SELECT * FROM users WHERE id = $1',
};
const res = await client.query(query, [5]);
console.log(res.rows);

Pg prepare в MySQL

PREPARE user_stmt FROM 'SELECT * FROM users WHERE id = ?';
SET @id = 1;
EXECUTE user_stmt USING @id;
DEALLOCATE PREPARE user_stmt;

Основное отличие в синтаксисе: в PostgreSQL в запросе используются позиционные плейсхолдеры $1, $2, в то время как в MySQL — знак вопроса ?. В Python и JS подготовка часто происходит неявно через параметризованные запросы.

Типичные ошибки
Ошибка подключения к базе данных
$conn = false;
$result = pg_prepare($conn, 'my_query', 'SELECT 1');
var_dump($result);
bool(false)

Ошибка возникает, если передать неверный ресурс соединения.

Некорректное имя подготовленного запроса
$conn = pg_connect('host=localhost dbname=test user=postgres');
$result = pg_prepare($conn, 'my-query', 'SELECT 1');
var_dump($result);
bool(false)

Имя запроса не должно содержать дефисы и другие специальные символы. Лучше использовать буквы, цифры и знак подчеркивания.

Синтаксическая ошибка в SQL-запросе
$conn = pg_connect('host=localhost dbname=test user=postgres');
$result = pg_prepare($conn, 'bad_query', 'SELCT * FROM users');
if ($result === false) {
    echo pg_last_error($conn);
}
ERROR:  syntax error at or near "SELCT"
LINE 1: SELCT * FROM users
Изменения в последних версиях PHP

Начиная с PHP 8.1, ресурсы PostgreSQL были заменены на объекты PgSql\Connection и PgSql\Result. Функция pg_prepare теперь возвращает объект PgSql\Result вместо ресурса, но это изменение обратно совместимо.

В PHP 8.0 существенных изменений в работе функции не было.

Расширенные примеры
Использование в транзакции
Пример php
$conn = pg_connect('host=localhost dbname=test user=postgres');
pg_query($conn, 'BEGIN');

pg_prepare($conn, 'update_balance', 'UPDATE accounts SET balance = balance + $1 WHERE id = $2');
pg_prepare($conn, 'insert_history', 'INSERT INTO transactions(account_id, amount) VALUES ($1, $2)');

pg_execute($conn, 'update_balance', [100, 123]);
pg_execute($conn, 'insert_history', [123, 100]);

pg_query($conn, 'COMMIT');
Работа с различными типами данных
Пример php
$conn = pg_connect('host=localhost dbname=test user=postgres');
pg_prepare($conn, 'complex_query', 'INSERT INTO products(name, price, active, tags) VALUES ($1, $2, $3, $4)');

$result = pg_execute($conn, 'complex_query', ['Ноутбук', 999.99, true, '{электроника,техника}']);
var_dump(pg_affected_rows($result));
int(1)
Повторное использование подготовленного запроса в цикле
Пример php
$conn = pg_connect('host=localhost dbname=test user=postgres');
pg_prepare($conn, 'insert_data', 'INSERT INTO measurements(value, sensor_id) VALUES ($1, $2)');

$data = [
    [22.5, 1],
    [23.1, 1],
    [21.8, 2],
    [24.3, 2]
];

foreach ($data as $row) {
    pg_execute($conn, 'insert_data', $row);
}
Использование с типизированными плейсхолдерами
Пример php
$conn = pg_connect('host=localhost dbname=test user=postgres');
pg_prepare($conn, 'typed_query', 'SELECT $1::text as fixed_text, $2::int[] as numbers');
$res = pg_execute($conn, 'typed_query', ['Пример', '{1,2,3}']);
print_r(pg_fetch_assoc($res));
Array
(
    [fixed_text] => Пример
    [numbers] => {1,2,3}
)
Получение метаданных подготовленного запроса
Пример php
$conn = pg_connect('host=localhost dbname=test user=postgres');
$result = pg_prepare($conn, 'meta_query', 'SELECT id, name FROM users WHERE age BETWEEN $1 AND $2');
$desc = pg_result_status($result, PGSQL_STATUS_STRING);
echo $desc;
PREPARE meta_query AS SELECT id, name FROM users WHERE age BETWEEN $1 AND $2

PHP pg_prepare function comments

En
Pg prepare Submits a request to create a prepared statement with the given parameters, and waits for completion