如何在PHP中获取PostgreSQL的自定义数据域类型?
如何在PHP中获取PostgreSQL的自定义数据域类型?
嘿,这个问题我之前也碰到过!PDO的getColumnMeta()方法确实没法直接告诉你列是否使用了自定义domain——它只会返回列的底层基础数据类型(比如你例子里的char(2)),完全不会带上domain的别名信息。不过别担心,我们可以直接查询PostgreSQL的系统元数据表来获取这些信息,下面给你两种实用的方法:
方法一:使用information_schema查询
PostgreSQL的information_schema视图里有专门存放domain和列信息的表,我们可以关联它们来找出哪些列属于自定义domain:
首先执行这个SQL查询,传入你的表名和schema(通常是public):
SELECT c.column_name, d.domain_name FROM information_schema.columns c LEFT JOIN information_schema.domains d ON c.udt_name = d.domain_name AND c.table_schema = d.domain_schema WHERE c.table_name = ? AND c.table_schema = ?
然后在PHP里把这个查询和你的数据查询结合起来,比如:
$dsn = 'pgsql:host=…; dbname=…'; $user = '…'; $password = '…'; $pdo = new PDO($dsn, $user, $password) or die('oops'); // 先查询列对应的domain信息 $targetTable = 'test'; $targetSchema = 'public'; $domainStmt = $pdo->prepare(" SELECT c.column_name, d.domain_name FROM information_schema.columns c LEFT JOIN information_schema.domains d ON c.udt_name = d.domain_name AND c.table_schema = d.domain_schema WHERE c.table_name = ? AND c.table_schema = ? "); $domainStmt->execute([$targetTable, $targetSchema]); // 把结果存成列名到domain的映射数组 $columnDomainMap = []; while ($row = $domainStmt->fetch(PDO::FETCH_ASSOC)) { if (!empty($row['domain_name'])) { $columnDomainMap[$row['column_name']] = $row['domain_name']; } } // 再查询表中的数据 $sql = 'SELECT data, etc FROM test'; $pds = $pdo->query($sql); // 现在就能结合映射数组判断列是否属于自定义domain了 $columnsCount = $pds->columnCount(); for ($i = 0; $i < $columnsCount; $i++) { $colMeta = $pds->getColumnMeta($i); $colName = $colMeta['name']; echo "列 {$colName} 的基础类型:{$colMeta['native_type']}"; if (isset($columnDomainMap[$colName])) { echo ",对应的自定义域:{$columnDomainMap[$colName]}"; } echo "\n"; }
方法二:直接查询pg_catalog系统表
如果你需要更底层的元数据,可以直接查PostgreSQL的pg_catalog表,这里的信息更全面:
SELECT a.attname AS column_name, t.typname AS domain_name FROM pg_attribute a JOIN pg_type t ON a.atttypid = t.oid JOIN pg_domain d ON t.oid = d.typoid WHERE a.attrelid = ?::regclass AND a.attnum > 0 AND NOT a.attisdropped;
在PHP里使用的方式和上面类似,把?替换成你的表名(比如'test')就能拿到对应的domain信息。
为什么getColumnMeta()不行?
简单来说,PostgreSQL在把结果返回给PDO的时候,会自动把domain类型解析成它的基础类型(比如你的emoji域会被解析成char(2)),所以PDO拿到的只是基础类型的元数据,完全不知道domain的存在——这也是为什么你看到两个列的getColumnMeta()输出没有区别的原因。
备注:内容来源于stack exchange,提问作者Manngo
相关产品推荐
相关产品推荐

