Qué es la clave externa
La clave externa en Oracle es una forma de relacionar varias tablas. Es un entrecruzamiento entre las tablas.
- Una clave externa es una columna o conjunto de columnas que se refiere a la clave principal o clave única en la misma tabla o en otra tabla
- Los valores de clave externa se basan en valores de datos y son construcciones puramente lógicas, no punteros físicos
- El valor de la clave externa debe coincidir con un valor de clave principal o un valor de clave único o será nulo.
Las restricciones de clave externa se denominan restricciones de integridad referencial. La tabla a la que se hace referencia se denomina tabla principal, mientras que la tabla con la clave externa se denomina tabla secundaria.
cómo usar la clave externa
Comprobemos con el ejemplo de EMP y DEPT.
SQL>CREATE TABLE "DEPT" ( "DEPTNO" NUMBER(2,0), "DNAME" VARCHAR2(14), "LOC" VARCHAR2(13), CONSTRAINT "PK_DEPT" PRIMARY KEY ("DEPTNO") ) SQL>CREATE TABLE "EMP" ( "EMPNO" NUMBER(4,0), "ENAME" VARCHAR2(10), "JOB" VARCHAR2(9), "MGR" NUMBER(4,0), "HIREDATE" DATE, "SAL" NUMBER(7,2), "COMM" NUMBER(7,2), "DEPTNO" NUMBER(2,0), CONSTRAINT "PK_EMP" PRIMARY KEY ("EMPNO") ); SQL> desc emp Name Null? Type EMPNO NOT NULL NUMBER(4) ENAME VARCHAR2(10) JOB VARCHAR2(9) MGR NUMBER(4) HIREDATE DATE SAL NUMBER(7,2) COMM NUMBER(7,2) DEPTNO NUMBER(2) SQL> SQL> desc dept Name Null? Type DEPTNO NOT NULL NUMBER(2) DNAME VARCHAR2(14) LOC VARCHAR2(13) SQL> insert into DEPT values(10, 'ACCOUNTING', 'NEW YORK'); insert into dept values(20, 'RESEARCH', 'DALLAS'); insert into dept values(30, 'RESEARCH', 'DELHI'); insert into dept values(40, 'RESEARCH', 'MUMBAI'); insert into emp values( 7698, 'Blake', 'MANAGER', 7839, to_date('1-5-2007','dd-mm-yyyy'), 2850, null, 10 ); insert into emp values( 7782, 'Clark', 'MANAGER', 7839, to_date('9-6-2008','dd-mm-yyyy'), 2450, null, 10 ); insert into emp values( 7788, 'Scott', 'ANALYST', 7566, to_date('9-6-2012','dd-mm-yyyy'), 3000, null, 20 ); insert into emp values( 7789, 'TPM', 'ANALYST', 7566, to_date('9-6-2017','dd-mm-yyyy'), 3000, null, null ); insert into emp values( 7560, 'T1OM', 'ANALYST', 7567, to_date('9-7-2017','dd-mm-yyyy'), 4000, null, 20 ); insert into emp values( 7790, 'TOM', 'ANALYST', 7567, to_date('9-7-2017','dd-mm-yyyy'), 4000, null, null ); SQL> select from emp; EMPNO ENAME JOB MGR HIREDATE SAL COMM DEPTNO 7698 BLAKE MANAGER 7839 01-MAY-07 2850 10 7782 CLARK MANAGER 7839 09-JUN-08 2450 10 7788 SCOTT ANALYST 7566 09-JUN-12 3000 20 7789 TPM ANALYST 7566 09-JUN-17 3000 7790 TOM ANALYST 7567 09-JUL-17 4000 7560 T1OM ANALYST 7567 09-JUL-17 4000 20
La tabla EMP contiene la columna DEPT_NO. y la tabla DEPT también contiene la columna DEPT_NO y es la clave principal de la tabla.
Ahora no queremos ninguna entrada en la tabla EMP donde DEPT_NO no coincida con DEPT_NO en la columna DEPT ya que no podemos tener un emp cuyo número de departamento no exista. Veamos si podemos hacer esto con la configuración actual
SQL> insert into emp values( 7790, 'TOM', 'ANALYST', 7567, to_date('9-7-2017','dd-mm-yyyy'), 4000, null, 50); 1 row created.
Pero esto tuvo éxito y la estructura ha causado un problema de integridad de datos
Para evitar este tipo de problemas de datos, podemos hacer cumplir las restricciones de clave externa en la tabla EMP.
Veamos de nuevo
drop table emp; drop table dept; SQL>CREATE TABLE "DEPT" ( "DEPTNO" NUMBER(2,0), "DNAME" VARCHAR2(14), "LOC" VARCHAR2(13), CONSTRAINT "PK_DEPT" PRIMARY KEY ("DEPTNO") ) SQL>CREATE TABLE "EMP" ( "EMPNO" NUMBER(4,0), "ENAME" VARCHAR2(10), "JOB" VARCHAR2(9), "MGR" NUMBER(4,0), "HIREDATE" DATE, "SAL" NUMBER(7,2), "COMM" NUMBER(7,2), "DEPTNO" NUMBER(2,0), CONSTRAINT "PK_EMP" PRIMARY KEY ("EMPNO"), CONSTRAINT "FK_DEPTNO" FOREIGN KEY ("DEPTNO") REFERENCES "DEPT" ("DEPTNO") ENABLE ); SQL> desc emp Name Null? Type EMPNO NOT NULL NUMBER(4) ENAME VARCHAR2(10) JOB VARCHAR2(9) MGR NUMBER(4) HIREDATE DATE SAL NUMBER(7,2) COMM NUMBER(7,2) DEPTNO NUMBER(2) SQL> SQL> desc dept Name Null? Type DEPTNO NOT NULL NUMBER(2) DNAME VARCHAR2(14) LOC VARCHAR2(13) SQL> insert into DEPT values(10, 'ACCOUNTING', 'NEW YORK'); insert into dept values(20, 'RESEARCH', 'DALLAS'); insert into dept values(30, 'RESEARCH', 'DELHI'); insert into dept values(40, 'RESEARCH', 'MUMBAI'); insert into emp values( 7698, 'Blake', 'MANAGER', 7839, to_date('1-5-2007','dd-mm-yyyy'), 2850, null, 10 ); insert into emp values( 7782, 'Clark', 'MANAGER', 7839, to_date('9-6-2008','dd-mm-yyyy'), 2450, null, 10 ); insert into emp values( 7788, 'Scott', 'ANALYST', 7566, to_date('9-6-2012','dd-mm-yyyy'), 3000, null, 20 ); insert into emp values( 7789, 'TPM', 'ANALYST', 7566, to_date('9-6-2017','dd-mm-yyyy'), 3000, null, null ); insert into emp values( 7560, 'T1OM', 'ANALYST', 7567, to_date('9-7-2017','dd-mm-yyyy'), 4000, null, 20 ); insert into emp values( 7790, 'TOM', 'ANALYST', 7567, to_date('9-7-2017','dd-mm-yyyy'), 4000, null, null );
Ahora intentemos ingresar la misma fila
SQL> insert into emp values( 7790, 'TOM', 'ANALYST', 7567, to_date('9-7-2017','dd-mm-yyyy'), 4000, null, 50); insert into emp values( 7790, 'TOM', 'ANALYST', 7567, to_date('9-7-2017','dd-mm-yyyy'), 4000, null, 50) * ERROR at line 1: ORA-02291: integrity constraint (SCOTT.FK_DEPTNO) violated - parent key not found
Así ha evitado las entradas de datos erróneos.
Lo mismo es el escenario con Eliminar de la tabla DEPT. No deberíamos eliminar las filas del departamento donde emp tiene algunos registros. Sin restricciones de clave externa, sucederá y causará datos incorrectos. Pero con la clave externa, esto se evitará
SQL> delete from dept where deptno=10; delete from dept where deptno=10 * ERROR at line 1: ORA-02292: integrity constraint (SCOTT.FK_DEPTNO) violated - child record found
Cláusulas de clave externa en la opción de eliminación
CONSTRAINT "FK_DEPTNO" FOREIGN KEY ("DEPTNO") REFERENCES "DEPT" ("DEPTNO") ENABLE ON DELETE [CASCADE |SET NULL]
Caso 1: Clave externa definida sin la opción ON DELETE
No podrá eliminar registros de la tabla principal si se encuentran registros en la tabla secundaria
Caso -2 Clave foránea definida con la opción ON DELETE SET NULL
Veamos cómo funciona
SQL> alter table emp add CONSTRAINT "FK_DEPTNO" FOREIGN KEY ("DEPTNO") REFERENCES "DEPT" ("DEPTNO") ON DELETE SET NULL; Table altered. SQL> select * from emp where empno=7698; EMPNO DEPTNO ------- ---- 7698 10 SQL> delete from dept where deptno=10; 1 row deleted. SQL> commit; Commit complete. SQL> select * from emp where empno=7698; EMPNO DEPTNO ------- ---- 7698
Entonces, al eliminar las filas de la tabla principal, la columna de clave externa de las filas secundarias se hace nula
Caso -3 Clave foránea definida con la opción ON DELETE CASCADE
SQL> alter table emp add CONSTRAINT "FK_DEPTNO" FOREIGN KEY ("DEPTNO") REFERENCES "DEPT" ("DEPTNO") ON DELETE cascade; Table altered. SQL> delete from dept where deptno=10; 1 row deleted. SQL> commit; Commit complete. SQL> select * from emp where deptno=10; ; no rows selected SQL>
Entonces, al eliminar las filas de la tabla principal, las filas secundarias también se eliminan
Alterar clave externa de tabla
También podemos crear una clave externa en Oracle después de la creación de la tabla
alter table emp add CONSTRAINT "FK_DEPTNO" FOREIGN KEY ("DEPTNO") REFERENCES "DEPT" ("DEPTNO") ;
Cómo descartar la restricción de clave externa
SQL> alter table emp drop constraint "FK_DEPTNO"; Table altered.
Cómo deshabilitar la restricción
SQL> alter table emp disable constraint "FK_DEPTNO"; Table altered.
Cómo habilitar la restricción
SQL> alter table emp enable constraint "FK_DEPTNO"; Table altered. SQL>
También lee
Restricción de verificación en Oracle
Restricción no nula en Oracle
Cómo agregar una clave principal en Oracle:la clave principal identifica de forma única la fila en la tabla. Cómo agregar una clave principal en Oracle, cómo eliminar una clave principal, cómo crear una clave compuesta identifiquemos la fila rápidamente. Oracle crea el índice único para la clave si no hay ningún índice disponible
eliminar consulta en Oracle
https://en.wikipedia.org/wiki/Foreign_key