You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.04.13 18:38:00