为什么atttypmod与character_maximum_length不同?

问题描述 投票:3回答:1

我正在将一些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是否安全?

postgresql postgresql-9.4 information-schema
1个回答
4
投票

你可以说从类型charvarchar的结果中减去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$

也就是说,对于字符和变量字符,它总是减去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的视图定义。

© www.soinside.com 2019 - 2024. All rights reserved.