postgresql NULL值的NOT LIKE行为

ar7v8xwq  于 2023-02-15  发布在  PostgreSQL
关注(0)|答案(2)|浏览(279)

我想获取表中除serial类型列之外的所有列。我能想到的最接近这个问题的查询是:

SELECT column_name FROM information_schema.columns
WHERE table_name = 'table1' AND column_default NOT LIKE 'nextval%'

但问题是它也会排除/过滤column_default值为空的行,我不知道Postgres的行为为什么是这样的,所以我不得不把我的查询改为这样:

SELECT column_name FROM information_schema.columns
WHERE table_name = 'table1'
AND ( column_default IS NULL OR column_default NOT LIKE 'nextval%')

欢迎提出任何更好的建议或理由。

x8goxv8g

x8goxv8g1#

大约null

'anything' NOT LIKE null产生null,而不是true
并且在WHERE子句中,只有true才有资格使用筛选表达式。
大多数函数在null输入时返回null(也有例外),这是null在任何RDBMS中的本质。
如果您需要一个 * 单一 * 表达式,您 * 可以 * 使用:

AND (column_default LIKE 'nextval%') IS NOT TRUE;

不过,这并没有缩短或缩短。Details in the manual.

正确的查询

您的查询仍然不可靠。在Postgres数据库中,表名本身并不唯一,您需要另外指定模式名,或者依赖当前的search_path来查找其中的第一个匹配项:
相关:

  • search_path如何影响标识符解析和"当前模式"
SELECT column_name
FROM   information_schema.columns
WHERE  table_name = 'hstore1'
AND    table_schema = 'public'   -- your schema!
AND   (column_default IS NULL
    OR column_default NOT LIKE 'nextval%');

更好,但仍然不是防弹的。以'nextval'开头的列默认值还不能生成serial。请参见:

  • 自动增量表列

为了确保这一点,请检查使用中的序列是否由pg_get_serial_sequence(table_name, column_name)列"拥有"。
我自己很少使用信息模式。那些缓慢、臃肿的视图保证了跨主要版本的可移植性--目的是移植到其他符合标准的RDBMS。但无论如何,有太多东西是不兼容的。甲骨文甚至没有实现信息模式(截至2015年)。
此外,信息模式中缺少有用的PostgreSQL特定列。对于这种情况,我可能会查询系统目录,如下所示:

SELECT *
FROM   pg_catalog.pg_attribute a
WHERE  attrelid = 'table1'::regclass
AND    NOT attisdropped   -- no dropped (dead) columns
AND    attnum > 0         -- no system columns
AND    NOT EXISTS (
   SELECT FROM pg_catalog.pg_attrdef d
   WHERE  (d.adrelid, d.adnum) = (a.attrelid, a.attnum)
   AND    d.adsrc LIKE 'nextval%'
   AND    pg_get_serial_sequence(a.attrelid::regclass::text, a.attname) <> ''
   );

更快、更可靠,但便携性较差。
The manual:
目录pg_attrdef存储列的默认值。列的主要信息存储在pg_attribute中(见下文)。只有显式指定默认值的列(在创建表或添加列时)才会在此处有条目。
'table1'::regclass使用search_path解析名称,这样可以避免歧义。您可以对名称进行架构限定以否决:'myschema.table1'::regclass.
相关:

  • 使用表名、字段名和模式名查找引用的表名
  • 获取Postgres中表列的默认值?
kb5ga3dv

kb5ga3dv2#

我认为您可以用途:

SELECT column_name *FROM* information_schema.columns
WHERE table_name = 'table1'
AND ( nvl(column_default,0) *NOT LIKE* 'nextval%');

相关问题