2010-03-10 7 views
6

Tengo dos tablas A y B como se definen a continuación.¿Cómo tener una combinación de teclas principal que puede tener valores nulos?

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 

columna A_2 en el cuadro A veces puede ser nulo, pero la combinación de A_1 y A_2 es ​​siempre único. Necesito que A_2 sea parte de la clave principal porque solo puedo hacer referencia a A_1 y A_2 como claves externas en la tabla B. El problema aquí es que la clave principal no puede ser nula. ¿Cómo resolver este problema? Cualquier respuesta será muy apreciada

Respuesta

21

Resuelve este problema al no tener esto como clave principal. Las claves principales no pueden ser NULL o, si son claves primarias compuestas, no pueden contener NULL. Hazlo un índice único en su lugar. Crea un campo de autonumeración para la clave principal.

2

No puede tener una columna nula en una clave principal, pero puede crear un índice único con columnas nulas en su lugar. Para conseguir que esto funcione en Oracle 10g, también tuve que añadir explícitamente una contraint único en la tabla:

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); 

Sin embargo, he intentado probar esta configuración, y no funciona como esperaba que lo haría. Por ejemplo:

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 

Bien, eso es lo que se espera. Sin fila de los padres, por lo que una fila no debe ser permitido en la tabla secundaria, sin embargo:

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

1 row created. 

parece que acaba de dejar esa fila se insertan sin fallar, a pesar de que no hay filas en T1 con 2, null ¡en absoluto!

SQL> commit; 

Commit complete. 

SQL> select * from t1; 

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

SQL> select * from b1; 

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

Me sorprendió este comportamiento, ya que el índice único en T1 se comporta como era de esperar que (sólo 1 fila se pueden insertar con 1, null, etc).

1

Si utiliza "diferible inicialmente diferido" en la clave principal, puede TENER valores NULOS ...

Cuestiones relacionadas