多列上没有强制执行唯一索引 - MySQL与Oracle的不同行为

时间:2013-02-20 03:36:07

标签: mysql

这个简单的脚本:

create table test (a integer not null, b integer, c integer not null);
create unique index test1 on test (a, b, c);
insert into test values(1, null, 1);
insert into test values(1, null, 1);
select * from test;

使用MySQL成功运行,但由于ORA-0001“违反了唯一约束”而失败。

我不确定标准对多个空列上的唯一索引的说法,但MySQL的行为可能与Oracle类似。

另见http://lists.mysql.com/mysql/183630

亚历山大。

1 个答案:

答案 0 :(得分:1)

根据设计,MySQL允许列中具有UNIQUE索引的多个NULL值。

MySQL上的BDB storage engine是一个例外,它不允许在coulmn中使用多个NULL值,并且上面有UNIQUE索引。

另一方面,Oracle在NULL值方面表现不同。当您在Oracle中的单个列上创建UNIQUE索引时,它将允许您有多个NULL值,因为NULL基本上意味着未知值,所以两个NULL值无法相互比较。不仅如此,在Oracle的情况下,NULL值不会存储在Index中。这意味着,当您在Oracle中的多个列上创建UNIQUE索引时,其中两列为NOT NULL而一列为NULLABLE,则不允许您插入两个具有相同列的记录值,即使一列包含NULL

考虑一下:

CREATE TABLE test (a NUMBER NOT NULL,
                   b NUMBER,
                   c NUMBER NOT NULL
                  );

INSERT INTO test VALUES (1, NULL, 1);
1 rows inserted.

INSERT INTO test VALUES (1, NULL, 1);

SQL Error: ORA-00001: unique constraint (RQ4151.UQ_TEST) violated
00001. 00000 -  "unique constraint (%s.%s) violated"
*Cause:    An UPDATE or INSERT statement attempted to insert a duplicate key.
           For Trusted Oracle configured in DBMS MAC mode, you may see
           this message if a duplicate entry exists at a different level.
*Action:   Either remove the unique restriction or do not insert the key.

这种情况发生了,因为Oracle没有在索引中存储NULL值,因此尝试比较索引中唯一性的NOT NULL列值,该值失败,导致错误被标记。