El consejo común con situaciones como esta es emplear deferrable constraints. Sin embargo, creo que estas situaciones casi siempre son un fracaso de la lógica de la aplicación o el modelo de datos. Por ejemplo, la inserción de un registro hijo y un registro primario en la misma transacción puede ser un problema si lo ejecutamos como dos declaraciones:
Mi datos de prueba:
SQL> select * from t23 order by id, parent_id
2/
ID PARENT_ID NAME
---------- ---------- ------------------------------
110 parent 1
111 parent 2
210 110 child 0
220 111 child 1
221 111 child 2
222 111 child 3
6 rows selected.
SQL>
La manera incorrecta de hacer las cosas:
SQL> insert into t23 (id, parent_id, name) values (444, 333, 'new child')
2/
insert into t23 (id, parent_id, name) values (444, 333, 'new child')
*
ERROR at line 1:
ORA-02291: integrity constraint (APC.T23_T23_FK) violated - parent key not
found
SQL> insert into t23 (id, parent_id, name) values (333, null, 'new parent')
2/
1 row created.
SQL>
Sin embargo, Oracle soporta una synatx INSERT de varias mesas, que nos permite insertar los registros primarios y secundarios en la misma instrucción, obviando así la necesidad de restricciones diferibles:
La situación en la que se encuentra es similar: desea actualizar la clave principal del registro principal pero no puede debido a la existencia de registros secundarios: Y no puede actualizar los registros secundarios porque allí no hay una clave padre Catch-22:
SQL> update t23
2 set id = 555
3 where id = 111
4/
update t23
*
ERROR at line 1:
ORA-02292: integrity constraint (APC.T23_T23_FK) violated - child record found
SQL> update t23
2 set parent_id = 555
3 where parent_id = 111
4/
update t23
*
ERROR at line 1:
ORA-02291: integrity constraint (APC.T23_T23_FK) violated - parent key not
found
SQL>
Una vez más, la solución es hacerlo en una sola instrucción:
SQL> update t23
2 set id = decode(id, 111, 555, id)
3 , parent_id = decode(parent_id, 111, 555, parent_id)
4 where id = 111
5 or parent_id = 111
6/
4 rows updated.
SQL> select * from t23 order by id, parent_id
2/
ID PARENT_ID NAME
---------- ---------- ------------------------------
110 parent 1
210 110 child 0
220 555 child 1
221 555 child 2
222 555 child 3
333 new parent
444 333 new child
555 parent 2
8 rows selected.
SQL>
La sintaxis de la instrucción UPDATE es un poco torpe, pero por lo general son kludges.El punto es que no deberíamos tener que actualizar las columnas de clave principal muy a menudo. De hecho, como la inmutabilidad es una de las características de la "clave primaria", no deberíamos tener que actualizarlas en absoluto. Necesitarlo es una falla del modelo de datos. Una forma de evitar tales fallas es usar una clave primaria sintética (sustituta), y simplemente aplicar la unicidad de la clave natural (también conocida como negocio) con una restricción única.
Entonces, ¿por qué Oracle ofrece restricciones diferibles? Son útiles cuando realizamos migraciones de datos o cargas masivas de datos. Nos permiten limpiar datos en la base de datos sin tablas intermedias. Realmente no deberíamos necesitarlos para las tareas de aplicación regulares.
"A veces el ID de un registro cambiará" - es posible que desee considerar el uso de una http://en.wikipedia.org/wiki/Surrogate_key para que esto no suceda ... –