Pg field table: примеры (PHP)
pg_field_table(PgSql\Result $result, int $field, bool $oid_only = false): string|int|falseОписание функции pg_field_table
Функция pg_field_table в PHP предназначена для получения имени таблицы, к которой принадлежит указанное поле в результате запроса PostgreSQL. Она помогает определить происхождение столбца, особенно в запросах с объединениями (JOIN), подзапросами или при выборке из представлений.
Функция используется при работе с расширением PostgreSQL (pgsql), когда необходимо программно определить источник данных для поля в наборе результатов. Это может быть полезно для построения динамических запросов, логирования или отладки.
- $result (ресурс) – обязательный. Ресурс результата запроса PostgreSQL, возвращаемый функциями
pg_query(),pg_query_params()илиpg_execute(). - $field (int) – обязательный. Порядковый номер поля в результате. Нумерация начинается с 0.
- $oid_only (bool) – необязательный. По умолчанию
false. Если установлено вtrue, функция возвращает OID (идентификатор объекта) таблицы вместо её имени.
Возвращаемые значения:
- Имя таблицы (string) – если таблица найдена и параметр
$oid_only = false. - OID таблицы (int) – если
$oid_only = true. - false – в случае ошибки (например, неверный номер поля).
- null – если поле не относится к конкретной таблице (например, результат вычисления или агрегатной функции).
Примеры использования
Запрос с простым выбором из одной таблицы.
<?php
$conn = pg_connect("host=localhost dbname=test user=postgres");
$result = pg_query($conn, "SELECT id, name FROM products");
// Получаем имя таблицы для поля с индексом 0 (id)
$tableName = pg_field_table($result, 0);
echo "Таблица для поля 'id': ". ($tableName ?: 'не определена');
// Для поля с индексом 1 (name)
$tableName = pg_field_table($result, 1);
echo "\nТаблица для поля 'name': ". ($tableName ?: 'не определена');
pg_free_result($result);
pg_close($conn);
?>Таблица для поля 'id': products Таблица для поля 'name': products
Запрос с объединением двух таблиц.
<?php
$conn = pg_connect("host=localhost dbname=test user=postgres");
$result = pg_query($conn,
"SELECT p.id, p.name, c.category_name \n FROM products p \n JOIN categories c ON p.category_id = c.id"
);
// Имя таблицы для первого поля (p.id)
$tableName = pg_field_table($result, 0);
echo "Таблица для поля 0: ". ($tableName ?: 'не определена');
// OID таблицы для второго поля (p.name)
$oid = pg_field_table($result, 1, true);
echo "\nOID таблицы для поля 1: ". ($oid ?: 'не определён');
// Поле из второй таблицы (c.category_name)
$tableName = pg_field_table($result, 2);
echo "\nТаблица для поля 2: ". ($tableName ?: 'не определена');
pg_free_result($result);
pg_close($conn);
?>Таблица для поля 0: products OID таблицы для поля 1: 24576 Таблица для поля 2: categories
<?php
$conn = pg_connect("host=localhost dbname=test user=postgres");
$result = pg_query($conn, "SELECT 1+2 as sum, * FROM products LIMIT 1");
$tableName = pg_field_table($result, 0); // Поле 'sum'
echo "Таблица для вычисляемого поля: ". (is_null($tableName) ? 'NULL' : $tableName);
$tableName = pg_field_table($result, 1); // Первое поле из products
echo "\nТаблица для поля из таблицы: ". ($tableName ?: 'не определена');
pg_free_result($result);
pg_close($conn);
?>Таблица для вычисляемого поля: NULL Таблица для поля из таблицы: products
Похожие функции в PHP
Возвращает название поля по его индексу в результате. Полезна для получения имени столбца, но не определяет таблицу-источник.
$fieldName = pg_field_name($result, 0); // 'id'Возвращает тип данных поля по его индексу (например, 'int4', 'varchar'). Не предоставляет информацию о таблице.
$fieldType = pg_field_type($result, 0); // 'int4'Получает метаинформацию о таблице в виде массива, включая имена и типы полей. Требует имя таблицы и соединение, но не результат запроса.
$meta = pg_meta_data($conn, 'products');
// Возвращает массив с описанием столбцов таблицыВыбор функции:
- pg_field_table – когда нужно определить таблицу-источник для конкретного поля в результате запроса, особенно с JOIN.
- pg_meta_data – для получения полной структуры таблицы без выполнения запроса.
- pg_field_name/type – для информации о самом поле (имя, тип), но не о его происхождении.
Альтернативы в других языках и СУБД
В psycopg2 нет прямой аналогии. Информацию о таблице-источнике можно получить через атрибуты курсора, например, cursor.description, но там нет имени таблицы. Обычно используют запросы к системным каталогам PostgreSQL.
import psycopg2
conn = psycopg2.connect("dbname=test user=postgres")
cursor = conn.cursor()
cursor.execute("SELECT p.id FROM products p")
# Имя таблицы не доступно напрямую
print(cursor.description[0].name) # 'id'
# Для получения таблицы можно использовать дополнительный запрос:
cursor.execute("""
SELECT table_name FROM information_schema.columns
WHERE table_schema='public' AND column_name='id';
""")
print(cursor.fetchone())('products',)Аналогично, прямой функции нет. Метаданные о полях доступны в массиве result.fields, но без информации о таблице. Требуется отдельный запрос к системным таблицам.
const { Client } = require('pg');
const client = new Client();
(async () => {
await client.connect();
const res = await client.query('SELECT id FROM products');
console.log(res.fields[0].name); // 'id'
// Имя таблицы отсутствует
await client.end();
})();id
В MySQL функция mysqli_fetch_field_direct возвращает объект с информацией о поле, включая свойство orgtable – исходную таблицу. Аналог pg_field_table с более прямой интеграцией.
<?php
$mysqli = new mysqli("localhost", "user", "pass", "test");
$result = $mysqli->query("SELECT id FROM products");
$field = $result->fetch_field_direct(0);
echo "Таблица: ". $field->orgtable;
?>Таблица: products
Можно получить информацию о происхождении полей через системный каталог pg_attribute и pg_class, но это требует сложных JOIN и знания OID таблиц.
SELECT a.attname, c.relname
FROM pg_attribute a
JOIN pg_class c ON a.attrelid = c.oid
WHERE a.attnum = 1 AND c.relname = 'products';attname | relname ---------+--------- id | products
Отличия: PHP функция pg_field_table уникальна своей простотой для PostgreSQL, предоставляя информацию напрямую из результата запроса. В других языках обычно требуются дополнительные запросы к системным таблицам.
Типичные ошибки
Передача индекса за пределами количества полей в результате.
<?php
$conn = pg_connect("host=localhost dbname=test user=postgres");
$result = pg_query($conn, "SELECT id FROM products");
$table = pg_field_table($result, 5); // Неверный индекс
echo "Результат: ". ($table === false ? 'false' : $table);
?>Результат: false
Передача переменной, которая не является ресурсом результата PostgreSQL.
<?php
$conn = pg_connect("host=localhost dbname=test user=postgres");
$result = "not a resource";
$table = @pg_field_table($result, 0); // Подавление ошибки для примера
echo "Результат: ". ($table === false ? 'false (ошибка)' : $table);
?>Результат: false (ошибка)
Ожидание имени таблицы для вычисляемого поля или поля из подзапроса.
<?php
$conn = pg_connect("host=localhost dbname=test user=postgres");
$result = pg_query($conn, "SELECT COUNT(*) FROM products");
$table = pg_field_table($result, 0);
echo "Таблица для агрегатной функции: ". (is_null($table) ? 'NULL' : $table);
?>Таблица для агрегатной функции: NULL
Обращение к функции после освобождения ресурса pg_free_result().
<?php
$conn = pg_connect("host=localhost dbname=test user=postgres");
$result = pg_query($conn, "SELECT id FROM products");
pg_free_result($result);
$table = @pg_field_table($result, 0);
echo "Результат: ". ($table === false ? 'false' : $table);
?>Результат: false
Изменения в последних версиях PHP
В PHP 8.0 функция pg_field_table не претерпела значительных изменений в поведении или синтаксисе. Однако, в связи с общей политикой PHP 8.0 по ужесточению типизации, передача неверных типов аргументов теперь вызывает более строгие ошибки TypeError вместо предупреждений.
В PHP 7.x функция работала стабильно. Важно отметить, что параметр $oid_only был введён давно и доступен с ранних версий PHP 5.x.
На момент написания статьи, в актуальных версиях PHP 8.1/8.2 не анонсированы изменения для pg_field_table. Функция остаётся частью стабильного расширения pgsql.
Расширенные примеры
Использование функции для безопасного добавления условий в запрос на основе происхождения поля.
<?php
$conn = pg_connect("host=localhost dbname=test user=postgres");
// Запрос с JOIN
$result = pg_query($conn,
"SELECT p.id, p.name, c.name as category FROM products p \n LEFT JOIN categories c ON p.category_id = c.id"
);
$fieldIndex = 2; // Допустим, мы хотим проверить поле 'category'
$tableName = pg_field_table($result, $fieldIndex);
if ($tableName === 'categories') {
echo "Поле принадлежит таблице categories, можно добавить условие WHERE c.name IS NOT NULL";
} elseif ($tableName === 'products') {
echo "Поле из таблицы products";
} else {
echo "Таблица не определена";
}
pg_free_result($result);
pg_close($conn);
?>Поле принадлежит таблице categories, можно добавить условие WHERE c.name IS NOT NULL
Автоматическое определение таблиц для всех полей в результате.
<?php
$conn = pg_connect("host=localhost dbname=test user=postgres");
$result = pg_query($conn,
"SELECT p.id, p.name, c.name as category, p.price * 1.2 as price_with_vat \n FROM products p \n JOIN categories c ON p.category_id = c.id"
);
$fieldCount = pg_num_fields($result);
for ($i = 0; $i < $fieldCount; $i++) {
$fieldName = pg_field_name($result, $i);
$tableName = pg_field_table($result, $i);
echo "Поле: $fieldName | Таблица: ". (is_null($tableName) ? 'Вычисляемое' : $tableName) . "\n";
}
pg_free_result($result);
pg_close($conn);
?>Поле: id | Таблица: products Поле: name | Таблица: products Поле: category | Таблица: categories Поле: price_with_vat | Таблица: Вычисляемое
Использование OID таблицы для выполнения системных запросов PostgreSQL, например, получение размера таблицы.
<?php
$conn = pg_connect("host=localhost dbname=test user=postgres");
$result = pg_query($conn, "SELECT * FROM products LIMIT 1");
$oid = pg_field_table($result, 0, true); // OID таблицы products
if ($oid) {
$sizeResult = pg_query($conn, "SELECT pg_total_relation_size($oid) as size");
$size = pg_fetch_result($sizeResult, 0, 'size');
echo "OID таблицы: $oid, Размер: $size байт";
pg_free_result($sizeResult);
}
pg_free_result($result);
pg_close($conn);
?>OID таблицы: 24576, Размер: 8192 байт
Определение, происходит ли поле из основной таблицы, представления или подзапроса.
<?php
$conn = pg_connect("host=localhost dbname=test user=postgres");
// Создадим простое представление
pg_query($conn, "CREATE OR REPLACE VIEW expensive_products AS SELECT id, name FROM products WHERE price > 1000");
$result = pg_query($conn, "SELECT * FROM expensive_products");
$tableName = pg_field_table($result, 0);
echo "Таблица для поля из представления: ". ($tableName ?: 'не определена');
// Очистка
pg_query($conn, "DROP VIEW expensive_products");
pg_free_result($result);
pg_close($conn);
?>Таблица для поля из представления: products
Примечание: Функция возвращает имя базовой таблицы, а не представления, так как представление – это виртуальная таблица.