Oracle没有区分空值和空字符串?

时间:2009-08-12 19:20:04

标签: database oracle

显然oracle似乎没有区分空字符串和空值。例如。

Select name from TABLE_A where id=100;
  ID   NAME
  100  null

Update TABLE_A set NAME='' where id=100;
SELECT -->
  ID   NAME
  100  null

SELECT length(NAME) FROM TABLE_A WHERE id=100;
  null

我想不出有什么理由可以建立Oracle以这种方式运行(它是否也在sqlplus中执行此操作? - 我通过java接口访问,引用的文章使用了php客户端)。

难道你至少不想区分0长度和未定义长度吗?这是一个已知的问题?某些特定目的的故意行为?数据库理论中长期存在的争议?是什么赋予了?

(这是由Matt Solnit对this question的回答提示的。)

5 个答案:

答案 0 :(得分:33)

Oracle非常非常老。

回到80's开发时(在有任何标准之前),他们认为这是一个好主意,然后给出Oracle存储其值的方式,它确实是。

以下是Oracle存储数据的方式(取自documentation):

alt text

数据中没有存储数据类型,只存储数据长度和数据本身。

如果NULL发生在具有值的两列之间,则它存储为单个字节,意味着列的长度为0(实际上为0xFF)。结尾NULL根本不存储。

因此要存储值'test'Oracle需要存储5个字节:04 74 65 73 74

但是,要存储空字符串和NULLOracle只需要将数据长度设置为0

如果您的数据要存储在每个价格20 Mb的{​​{1}}个硬盘上,那就太聪明了。

后来,当标准出现时,它不再是一个好主意了,但那时已经有很多很多代码依赖于5,000$NULL是同一个东西。

''进行此类区分会破坏代码。

要解决此问题,他们会将VARCHAR重命名为VARCHAR(这不是任何标准的一部分),并指出VARCHAR2从不区分VARCHAR2和一个空字符串,并敦促每个人使用此数据类型。

现在他们可能正在等待使用NULL数据库中VARCHAR的最后一个人死亡。

答案 1 :(得分:3)

你可能想在两年多前在OTN上阅读这篇关于这个确切主题的长篇有趣的讨论:http://forums.oracle.com/forums/thread.jspa?threadID=456874&start=0&tstart=0

此致 罗布。

答案 2 :(得分:1)

这就是为什么像Date这样聪明的人会说你永远不应该使用空值。

(不,我必须准确。实际上,这只是他过去几十年来提到的支持这一说法的几百个理由中的一个。)

修改

我其实也想回应这个:

“让VARCHAR做这样的区分会打破大量的代码。”

是的,当然,通过在每次更新时将“空字符串”替换为空来至少打破标准的精神是一个较小的邪恶?

(注意:null不等于任何东西,甚至不是自己,所以在将空字符串分配给列后,oracle会在该列中为您提供一个与您想要的值不同的值出现在那里。哇。)

答案 3 :(得分:0)

看起来Oracle已经说过,这种行为可能会在将来的版本中发生变化。什么时候释放它将被提及。

如果您有权访问metalink,请查看注释:1011340.6(遗憾的是,由于限制,我无法复制此处注释的内容)

如果您无法访问metalink,请查看10g第2版文档中的以下内容here

答案 4 :(得分:0)

@Ian,回复你。

Oracle触发器可以引用它们创建的表:

create table t (id number(10) );

create or replace trigger  t_bir before insert  on  t for each row
declare
  l_id t.id%type;
begin
  select id
  into   l_id
  from   t
  where  id = :new.id;
exception
  when no_data_found then 
    null;
end;
/


SQL> insert into t values (20);

1 row is created.


SQL> select * from t;

        ID
----------
        20