Pg escape identifier: примеры (PHP)
pg_escape_identifier(PgSql\Connection $connection, string $data): stringФункция pg_escape_identifier применяется для экранирования идентификаторов (имен таблиц, столбцов, схем) в запросах к PostgreSQL. Её основная задача - предотвращение SQL-инъекций и корректная обработка идентификаторов, содержащих специальные символы или зарезервированные слова.
Использование актуально при динамическом формировании SQL-запросов, где имена объектов базы данных зависят от пользовательского ввода или внешних данных.
Аргументы функции:
- $connection (ресурс соединения, необязательный с PHP 8.1) - идентификатор подключения к PostgreSQL. Если не указан, используется последнее соединение.
- $data (string) - строка с идентификатором, который требуется экранировать.
Возвращаемое значение: экранированная строка или false при ошибке.
<?
$conn = pg_connect('dbname=test');
$table = 'user table';
$escaped = pg_escape_identifier($conn, $table);
echo 'SELECT * FROM ' . $escaped . ';';
?>SELECT * FROM "user table";
<?
$conn = pg_connect('dbname=test');
$column = 'group';
$escaped = pg_escape_identifier($column);
echo 'SELECT ' . $escaped . ' FROM users;';
?>SELECT "group" FROM users;
<?
$conn = pg_connect('dbname=test');
echo pg_escape_identifier($conn, 'order');
?>"order"
- pg_escape_literal - экранирует значения для SQL-запросов, добавляя кавычки. Используется для скалярных значений, а не идентификаторов.
- pg_escape_string - экранирует спецсимволы в строках, но не добавляет кавычки. Менее безопасна для идентификаторов, чем pg_escape_identifier.
- Подготовленные выражения (pg_query_params) - наиболее безопасный способ работы с данными, но не поддерживают динамические идентификаторы.
Предпочтительнее использовать pg_escape_identifier именно для имен таблиц и столбцов, а подготовленные выражения - для значений.
from psycopg2 import sql
ident = sql.Identifier('user table')
query = sql.SQL('SELECT * FROM {}').format(ident)
print(query.as_string(conn))SELECT * FROM "user table"
const { Client } = require('pg');
const client = new Client();
async function escapeExample() {
const ident = 'user table';
const query = `SELECT * FROM "${ident}"`;
// Ручное экранирование
const escaped = ident.replace(/\"/g, '\"\"');
console.log(`SELECT * FROM "${escaped}"`);
}SELECT * FROM "user table"
Pg escape identifier в MySQL
SET @table = 'user table';
SET @query = CONCAT('SELECT * FROM `', REPLACE(@table, '`', '``'), '`');
SELECT @query;SELECT * FROM `user table`
<?
$conn = pg_connect('dbname=test');
$table = pg_escape_identifier($conn, 'my table');
// Ошибка: пропущены кавычки вокруг идентификатора
$query = 'SELECT * FROM ' . $table;
echo $query;
?>SELECT * FROM "my table"
Функция не добавляет кавычки автоматически - их нужно включать в запрос.
<?
$conn = pg_connect('dbname=test');
$value = pg_escape_identifier($conn, "O'Reilly");
$query = 'SELECT * FROM users WHERE name = ' . $value;
echo $query;
?>SELECT * FROM users WHERE name = "O'Reilly"
Для значений следует использовать pg_escape_literal или подготовленные выражения.
- PHP 8.1 - параметр
$connectionстал необязательным. При его отсутствии используется последнее установленное соединение. - PHP 8.0 - улучшена обработка ошибок, функция теперь более строго типизирована.
- PHP 7.0 - добавлена поддержка специальных символов Unicode в идентификаторах.
<?
$conn = pg_connect('dbname=test');
$table = 'user orders';
$columns = ['id', 'order date', 'amount'];
$escapedCols = array_map(fn($col) => pg_escape_identifier($conn, $col), $columns);
$query = 'SELECT ' . implode(', ', $escapedCols) .
' FROM ' . pg_escape_identifier($conn, $table) .
' WHERE ' . pg_escape_identifier($conn, 'order date') . ' > NOW() - INTERVAL \'7 days\'';
echo $query;
?>SELECT "id", "order date", "amount" FROM "user orders" WHERE "order date" > NOW() - INTERVAL '7 days'
<?
$conn = pg_connect('dbname=test');
// Неправильный подход:
$fullName = 'public.user table';
$escapedWrong = pg_escape_identifier($conn, $fullName);
echo 'Неправильно: ' . $escapedWrong . '\n';
// Правильный подход:
$parts = explode('.', 'public.user table');
$escapedParts = array_map(fn($part) => pg_escape_identifier($conn, $part), $parts);
$escapedCorrect = implode('.', $escapedParts);
echo 'Правильно: ' . $escapedCorrect;
?>Неправильно: "public.user table" Правильно: "public"."user table"
<?
$conn = pg_connect('dbname=test');
$tables = ['sales_2024', 'user data', 'order-items'];
foreach ($tables as $table) {
$escaped = pg_escape_identifier($conn, $table);
$countQuery = 'SELECT COUNT(*) as cnt FROM ' . $escaped;
echo $countQuery . '\n';
}
?>SELECT COUNT(*) as cnt FROM "sales_2024" SELECT COUNT(*) as cnt FROM "user data" SELECT COUNT(*) as cnt FROM "order-items"