我正在将一些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是安全的吗?
答案 0 :(得分:3)
对于类型char
和varchar
,从结果中减去4是很安全的。 information_schema.columns
视图的作用是调用函数informatoin_schema._pg_char_max_length
(这是您的区别,因为您没有),它的主体是:
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
的视图定义。