问题描述
create table test
(
id varchar2(10) check( length(trim(id)) > 0),primary key(id)
)
insert into test values (' '); -- this works
我希望此检查约束停止此插入。但是,它仍然被插入。为什么?
解决方法
问题是 TRIM(' ')
返回 NULL
而 LENGTH(NULL)
也给出 NULL
(不是 0)
试试 NVL(LENGTH(TRIM(' ')),0) > 0
或
试试TRIM(ID) IS NOT NULL
声明约束可以返回 null aka 'unknown' 并被认为不违反约束的代码段。只有返回 false 才违反约束。至少按照 Oracle 12c
See Oracle Concept page about constraints
,对所见所闻的解释:
-
如果
str
完全由空格组成,则trim(str)
是空字符串。 -
Oracle 将“空字符串”视为与
null
(varchar2
数据类型,重要时)相同,公然违反 SQL 标准。 Oracle 在这方面甚至不一致 - 有(极少数)例外,其中空字符串实际上被视为“空字符串”(例如,在串联中)。 -
根据定义,
null
的长度是null
(特别是不为零)。 -
在 SQL 中,像
null > 0
这样的条件的计算结果为unknown
(在这些条件中容纳null
所需的三值逻辑中)。 -
在检查约束中,
unknown
被视为与true
相同。这与其他条件(在 SQL 语句中 - 在where
子句、连接条件等中)中的处理不同,其中unknown
被视为与false
相同。例如,这里记录了这一点:https://docs.oracle.com/cd/B19306_01/server.102/b14200/clauses002.htm - 请参阅检查约束部分的第一段。
问题的正确解决方案:
应直接检查某些内容是否为空,使用 is null
或 is not null
条件。不要为此使用 length
。
像这样:
check( trim(id) is not null )