postgresql - 为什么 atttypmod 不同于 character_maximum_length?

标签 postgresql postgresql-9.4 information-schema

我正在将一些 information_schema 查询转换为系统目录查询,但我得到了不同的字符最大长度结果。

SELECT column_name, 
    data_type , 
    character_maximum_length AS "maxlen"
FROM information_schema.columns 
WHERE table_name = 'x'

返回我期望的结果,例如:

city    character varying   255
company character varying   1000

等价目录查询

SELECT attname,
       atttypid::regtype  AS datatype,
       NULLIF(atttypmod, -1) AS maxlen
FROM   pg_attribute
WHERE  CAST(attrelid::regclass AS varchar) = 'x'
AND    attnum > 0
AND    NOT attisdropped

似乎返回每个长度 + 4:

city    character varying   259
company character varying   1004

为什么不同?总是简单地从结果中减去 4 是否安全?

最佳答案

对于 charvarchar 类型,您可以说从结果中减去 4 是安全的。 information_schema.columns View 在幕后所做的是它调用函数 informatoin_schema._pg_char_max_length(这是你的区别,因为你没有) , 哪个 body 是:

CREATE OR REPLACE FUNCTION information_schema._pg_char_max_length(typid oid, typmod integer)
 RETURNS integer
 LANGUAGE sql
 IMMUTABLE PARALLEL SAFE STRICT
AS $function$SELECT
  CASE WHEN $2 = -1 /* default typmod */
       THEN null
       WHEN $1 IN (1042, 1043) /* char, varchar */
       THEN $2 - 4
       WHEN $1 IN (1560, 1562) /* bit, varbit */
       THEN $2
       ELSE null
  END$function$

也就是说,对于 chars 和 varchars,它总是减去 4。 这使得您的查询不等同于它实际需要连接到 pg_type 以建立列的 typid 并将值包装在函数中以具有的程度它返回正确的值。这是因为事实上,有更多的事情在起作用。如果你想简化,你可以在没有连接的情况下进行(虽然它不是防弹的):

SELECT attname,
       atttypid::regtype  AS datatype,
       NULLIF(information_schema._pg_char_max_length(atttypid, atttypmod), -1) AS maxlen
FROM   pg_attribute
WHERE  CAST(attrelid::regclass AS varchar) = 'x'
AND    attnum > 0
AND    NOT attisdropped

这应该可以为您完成。如果您想进一步调查此事,请参阅 information_schema.columns 的 View 定义。

关于postgresql - 为什么 atttypmod 不同于 character_maximum_length?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/52376045/

相关文章:

mysql - 根据 INFORMATION_SCHEMA 中的选择进行更新

Postgresql 函数返回多个选择语句

postgresql - 如何创建将父 ID 和祖 parent ID 插入数组的递归 CTE 查询

ruby-on-rails - 英雄数据库 :pull failing due to lack of password when I haven't specified a password

postgresql - 如何区分(和格式化) "empty"文本字段

postgresql - 用户 postgres 启动使所有 CPU 100% 使用的进程

postgresql - split_part 函数从第 n 次拆分到字符串末尾

ruby-on-rails - 以rails形式提交数组元素

mysql - 如何从 MySQL 中的 information_schema 获取主键索引前缀长度?

mysql - 在所有表中插入单个 table_name 作为列值