NOT LIKE 与 NULL 值的行为

问题描述 投票:0回答:4

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

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%')

欢迎任何更好的建议或背后的理由。

sql postgresql null information-schema
4个回答
53
投票

关于
null

'anything' NOT LIKE null
产生
null
,而不是
true

并且只有
true
才符合
WHERE
子句中的筛选表达式。

大多数函数在

null
输入上返回
null
(也有例外)。这就是
任何
适当的 RDBMS 中 null 的本质。

如果您想要单个表达式,您可以使用:

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

不过,这并没有更短或更快。 详情请参阅手册。

正确查询

您的查询仍然不可靠。单独的表名在 Postgres 数据库中并不唯一,您需要另外指定架构名称或依赖当前的

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。但太多无论如何都是不相容的。 Oracle 甚至没有实现信息模式(截至 2015 年)。

此外,信息模式中缺少有用的 Postgres 特定列。对于这种情况,我可能会像这样查询系统目录:

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) <> ''
   );

更快、更可靠,但便携性较差。

说明书:

目录

pg_attrdef
存储列默认值。主要 有关列的信息存储在
pg_attribute
中(见下文)。仅有的 显式指定默认值的列(当表为 创建或添加列)将在此处有一个条目。

'table1'::regclass
使用
search_path
来解析名称,这样可以避免歧义。您可以对名称进行架构限定以推翻:
'myschema.table1'::regclass

相关:


0
投票

最简单的方法是:

where length(column_name) > 0

0
投票

其中 isnull(column_name, '') 不像 '%somevalue%' 对我有用。 当我想在结果中包含 NULL 作为默认值时,将其转换为空白字符可以进行评估。


-2
投票

我想你可以使用:

SELECT column_name *FROM* information_schema.columns
WHERE table_name = 'table1'
AND ( nvl(column_default,0) *NOT LIKE* 'nextval%');
© www.soinside.com 2019 - 2024. All rights reserved.