Как получить комбинацию первичных ключей, которая может иметь нулевые значения? - PullRequest
6 голосов
/ 10 марта 2010

У меня есть две таблицы 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_2 в таблице A иногда может быть нулевым, но комбинация A_1 и A_2 всегда уникальна. Мне нужно, чтобы A_2 был частью первичного ключа, потому что только тогда я могу ссылаться на A_1 и A_2 на них как на внешние ключи в таблице B. Проблема в том, что первичный ключ не может быть нулевым. Как решить эту проблему? Любой ответ будет высоко оценен

Ответы [ 3 ]

23 голосов
/ 10 марта 2010

Вы решаете эту проблему, не имея ее в качестве первичного ключа. Первичные ключи не могут быть NULL или, если они составные первичные ключи, не могут содержать NULL. Вместо этого сделайте уникальный индекс. Создайте поле автономного номера для первичного ключа.

2 голосов
/ 10 марта 2010

Вы не можете иметь нулевой столбец в первичном ключе, но вместо этого вы можете создать уникальный индекс с нулевыми столбцами. Чтобы это работало в 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, вообще нулевым!

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, нулем и т. Д.).

1 голос
/ 26 июля 2013

Если вы используете «deferrable первоначально deferred» для первичного ключа, вы можете иметь значения NULL ...

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...