Saltar la navegación

7.5.- Interbloqueos

Ejemplo de interbloqueo entre dos tablas con cancelación de bloqueo automático a nivel de transacción.

Intentamos crear dos tablas con referencias cruzadas, es decir, la primera hace referencia a la segunda que aún no está creada y viceversa. Vamos a solucionar el problema del interbloqueo considerando la transacción como DEFERRED, es decir la comprobación de las restricciones se hará en diferido.

Si creo la primera tabla y hago referencia a la segunda, se producirá un error, aún no existe la segunda tabla:

CREATE TABLE Gallina(

idGallina number(3) PRIMARY KEY,

idHuevo number(3)  REFERENCES Huevo(idHuevo));

CREATE TABLE Huevo(

idHuevo number(3)  PRIMARY KEY,

idGallina number(3) REFERENCES Gallina(idGallina));


Informe de error -,

Error SQL: ORA-00942: la tabla o vista no existe

00942. 00000 - "table or view does not exist"

*Cause:

Podemos crear ambas tablas sólo especificando cual es la PK en cada una y a continuación ALTER TABLE para añadirle la referencia a la otra tabla.

CREATE TABLE Gallina(

idGallina number(3)  PRIMARY KEY,

idHuevo  number(3) );

CREATE TABLE Huevo(

idHuevo  number(3)  PRIMARY KEY,

idGallina  number(3) );

ALTER TABLE Gallina ADD CONSTRAINT fkRefHuevo

FOREIGN KEY(idHuevo) REFERENCES Huevo(idHuevo);

ALTER TABLE Huevo ADD CONSTRAINT fkRefGallina

FOREIGN KEY(idGallina) REFERENCES Gallina(idGallina);

Intentamos insertar un registro en cada una:

INSERT INTO Gallina VALUES(4, 5);

INSERT INTO Huevo VALUES(5, 4);

COMMIT;


Da error en las órdenes de inserción, ya que al insertar en la primera tabla, aún no tenemos dato en la segunda y exactamente igual al insertar en la segunda.

Si añadimos INITIALLY DEFERRED después de  REFERENCES en la orden ALTER TABLE la comprobación se hará después de commit y aunque aún no existan datos en la segunda tabla nos permitirá insertar el registro en la primera.

ALTER TABLE Gallina ADD CONSTRAINT fkRefHuevo

FOREIGN KEY(idHuevo) REFERENCES Huevo(idHuevo) INITIALLY DEFERRED;

ALTER TABLE Huevo ADD CONSTRAINT fkRefGallina

FOREIGN KEY(idGallina) REFERENCES Gallina(idGallina) INITIALLY DEFERRED;

INSERT INTO Gallina VALUES(4, 5);

INSERT INTO Huevo VALUES(5, 4);

COMMIT;


Las sentencias  para borrar las constraints  y las tablas tras el ejemplo, son:

ALTER TABLE Huevo DROP CONSTRAINT fkRefGallina;

ALTER TABLE Gallina DROP CONSTRAINT fkRefHuevo;

DROP TABLE Huevo;

DROP TABLE Gallina;