如何使用可能具有空值的主键组合?

时间:2010-03-10 10:01:46

标签: oracle constraints

我有两张表A和B,如下所示。

create table A
(
  A_1 varchar2(10) NOT NULL,
  A_2 varchar2(10),
  A_3 varchar2(10),
  constraint A_PK primary key (A_1,A_2)
)
TABLE A DATA
A_1      |A_2   |A_3
1111     abc     some_text1
1111     null    some_text1
1112     abc     some_text2
1113     def     some_text3

   create table B
   (
     B_1 varchar2(10) NOT NULL,
     B_2 varchar2(10),
     B_3 varchar2(10),
     constraint B_PK primary key (B_1,B_2,B_3),
     constraint B_FK foreign key (B_1,B2) references A(A_1,A_2)
   )
TABLE B DATA
B_1    | B_2    |B_3
1111    abc      text1
1111    null     text2
1111    null     text3
1111    null     text4 

表A中的A_2列有时可以为null,但A_1和A_2的组合始终是唯一的。我需要A_2成为主键的一部分,因为那时我只能将A_1和A_2引用为表B中的外键。这里的问题是主键不能为空。如何解决这个问题呢? 任何回复都将受到高度赞赏

3 个答案:

答案 0 :(得分:23)

您可以通过不将其作为主键来解决此问题。主键不能是NULL,或者如果它们是复合主键,则不能包含NULL。改为使其成为唯一的索引。为主键创建自动编号字段。

答案 1 :(得分:2)

主键中不能包含空列,但您可以使用空列创建唯一索引。为了在Oracle 10g中实现这一点,我还必须在表格中明确添加一个独特的约束:

create table t1 (a1 integer not null,
                 a2 integer,
                 a3 integer);

create unique index t1_uk1 on t1(a1, a2);

alter table t1 add constraint t1_cuk1 unique (a1, a2);

create table b1 (b1 integer not null, b2 integer, b3 integer);

create index b1_idx1 on b1 (b1, b2);

alter table b1 add constraint b1_fk1 
  foreign key (b1, b2) references t1 (a1, a2);  

但是,我尝试测试这个设置,它不能像我预期的那样工作。例如:

SQL> insert into t1 values (1, null, 1);

1 row created.

SQL> insert into b1 values (1, 1, 1);
insert into b1 values (1, 1, 1)
*
ERROR at line 1:
ORA-02291: integrity constraint (B1_FK1) violated - parent key not
found

好的,这就是预期的。父级中没有行,因此不应在子表中允许行:

SQL> insert into b1 values (2, null, 1);

1 row created.

看起来它只是让该行插入而不会失败,即使t1中没有行有2,null也是如此!

SQL> commit;

Commit complete.

SQL> select * from t1;

        A1         A2         A3
---------- ---------- ----------
         1                     1

SQL> select * from b1;

        B1         B2         B3
---------- ---------- ----------
         2                     1

我对此行为感到惊讶,因为t1上的唯一索引的行为与您期望的一样(只有1行可以插入1,null等)。

答案 2 :(得分:1)

如果在主键上使用“deferrable initial deferred”,则可以使用NULL值...

相关问题