为什么这个检查约束在检查长度时不起作用?

问题描述

create table test
(

   id varchar2(10) check( length(trim(id)) > 0),primary key(id)
)

insert into test values (' '); -- this works

我希望此检查约束停止此插入。但是,它仍然被插入。为什么?

解决方法

问题是 TRIM(' ') 返回 NULLLENGTH(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

Snippet stating that constraints can return null aka 'unknown'

,

对所见所闻的解释:

  1. 如果 str 完全由空格组成,则 trim(str) 是空字符串。

  2. Oracle 将“空字符串”视为与 nullvarchar2 数据类型,重要时)相同,公然违反 SQL 标准。 Oracle 在这方面甚至不一致 - 有(极少数)例外,其中空字符串实际上被视为“空字符串”(例如,在串联中)。

  3. 根据定义,null 的长度是 null(特别是不为零)。

  4. 在 SQL 中,像 null > 0 这样的条件的计算结果为 unknown(在这些条件中容纳 null 所需的三值逻辑中)。

  5. 检查约束中,unknown 被视为与 true 相同。这与其他条件(在 SQL 语句中 - 在 where 子句、连接条件等中)中的处理不同,其中 unknown 被视为与 false 相同。例如,这里记录了这一点:https://docs.oracle.com/cd/B19306_01/server.102/b14200/clauses002.htm - 请参阅检查约束部分的第一段。

问题的正确解决方案:

直接检查某些内容是否为空,使用 is nullis not null 条件。不要为此使用 length

像这样:

check( trim(id) is not null )