我知道它确实将“”视为NULL
,但这并不能告诉我为什么会这样。据我了解的SQL规范,“”与NULL
-是一个有效的数据,而另一个则表示缺少相同的信息。
随意推测,但请说明是否是这种情况。如果有Oracle的任何人可以对此发表评论,那就太好了!
我知道它确实将“”视为NULL
,但这并不能告诉我为什么会这样。据我了解的SQL规范,“”与NULL
-是一个有效的数据,而另一个则表示缺少相同的信息。
随意推测,但请说明是否是这种情况。如果有Oracle的任何人可以对此发表评论,那就太好了!
Answers:
我相信答案是甲骨文非常老。
早在建立SQL标准之前,Oracle就做出了以下设计决定:VARCHAR
/ VARCHAR2
列中的空字符串NULL
是NULL ,并且只有一种NULL含义(有些关系理论家会区分从未提示过的数据,存在答案但用户不知道的数据,没有答案的数据等,所有这些都构成某种意义NULL
。
到SQL标准出现并同意NULL
并且空字符串是不同的实体时,已经有Oracle用户使用了假定两者相等的代码。因此,Oracle基本上可以选择破坏现有代码,违反SQL标准或引入某种初始化参数的选项,这些参数可能会更改潜在大量查询的功能。在这三个选项中,违反SQL标准(IMHO)的破坏最少。
Oracle保留了VARCHAR
在将来的版本中更改数据类型以遵守SQL标准的可能性(这就是每个人都VARCHAR2
在Oracle中使用的原因,因为该数据类型的行为可以保证将来保持不变)。
Tom Kyte Oracle副总裁:
零长度的varchar被视为NULL。
''不被视为NULL。
分配给char(1)时的''变为'(字符类型为空白填充字符串)。
''在分配给varchar2(1)时变为'',这是Oracle中的零长度字符串而零长度字符串为NULL(不长'')
''
将其隐式转换为VARCHAR2时,会出现最令人困惑的情况,例如cast('' as char(1)) is null
……令人惊讶的是
我怀疑如果您像以前的开发人员那样思考Oracle,将它作为数据输入系统的光荣后端,这在很大程度上会更有意义。数据库中的每个字段都对应一个数据输入操作员在其屏幕上看到的格式的字段。如果操作员未在字段中键入任何内容,无论是“生日”还是“地址”,则该字段的数据均为“未知”。操作员无法指出某人的地址确实是一个空字符串,无论如何这实际上没有多大意义。
Oracle文档警告开发人员注意此问题,至少可以追溯到版本7。
Oracle选择通过“不可能的值”技术来表示NULL。例如,数字位置的NULL将存储为“减零”,这是不可能的值。计算产生的任何负零将在存储之前转换为正零。
Oracle还错误地选择将长度为零的VARCHAR字符串(空字符串)视为不可能的值,并且是表示NULL的合适选择。事实证明,空字符串远非不可能的值。甚至在字符串串联操作下的身份!
Oracle文档警告数据库设计人员和开发人员,某些将来的Oracle版本可能会破坏空字符串和NULL之间的这种关联,并破坏依赖于该关联的任何代码。
除了不可能的值外,还有一些标记NULLS的技术,但是Oracle没有使用它们。
(我在上面使用“位置”一词来表示行与列的交集。)
空字符串与NULL相同,只是因为与两个字符串(空字符串和null)不同时的情况相比,它的“较小危害”。
在NULL和空String不相同的语言中,必须始终检查这两个条件。
not null
在列上设置约束,然后仅检查空字符串即可。
书中的例子
set serveroutput on;
DECLARE
empty_varchar2 VARCHAR2(10) := '';
empty_char CHAR(10) := '';
BEGIN
IF empty_varchar2 IS NULL THEN
DBMS_OUTPUT.PUT_LINE('empty_varchar2 is NULL');
END IF;
IF '' IS NULL THEN
DBMS_OUTPUT.PUT_LINE(''''' is NULL');
END IF;
IF empty_char IS NULL THEN
DBMS_OUTPUT.PUT_LINE('empty_char is NULL');
ELSIF empty_char IS NOT NULL THEN
DBMS_OUTPUT.PUT_LINE('empty_char is NOT NULL');
END IF;
END;
因为不将其视为NULL也不特别有用。
如果您在Oracle的这方面犯了错误,通常会立即注意到。但是,在SQL Server中,它似乎可以正常工作,并且仅当有人输入空字符串而不是NULL时,问题才会出现(也许来自.net客户端库,其中null与“”不同,但通常将它们相同)。
我并不是说甲骨文是对的,但是在我看来,这两种方法几乎都同样糟糕。
事实上,我有什么,但困难与甲骨文打交道,包括无效的日期时间值(不能打印,转换或什么,只是看着与DUMP()函数),它们允许被插入到数据库中,显然是经过了一些越野车客户端版本作为二进制列!保护数据库完整性非常重要!
Oracle对NULL链接的处理:
http://digitalbush.com/2007/10/27/oracle-9i-null-behavior/
http://jeffkemponoracle.com/2006/02/empty-string-andor-null.html
首先,Oracle并不总是将null和null字符串视为相同。根据定义,空字符串是不包含任何字符的字符串。这与null完全不同。根据定义,NULL是指没有数据。
五六年前,Oracle对空字符串的处理方式与对空字符串的处理方式有所不同。虽然像null一样,null字符串等于所有内容,并且不同于所有内容(我认为null很好,但null字符串完全错误),但至少length(null string)将返回0,因为null字符串应为零长度的字符串。
当前在Oracle中,length(null)返回null,我猜是可以的,但是length(null string)也返回null,这完全是错误的。
我不明白为什么他们决定开始将这两个不同的“值”相同地对待。它们意味着不同的事物,程序员应具有以不同方式对每种事物进行操作的能力。他们改变了方法论的事实告诉我,他们对如何对待这些价值观一无所知。
NULL
与null值的字符串之间存在任何区别,而且这种区别是没有意义的。恐怕这个答案是一个完整的幻想。