Una clave externa es un conjunto de atributos en una tabla que hace referencia a la clave principal de otra tabla, vinculando estas dos tablas. En el contexto de las bases de datos relacionales , una clave externa está sujeta a una restricción de dependencia de inclusión que establece que las tuplas que consisten en los atributos de la clave externa en una relación , R, también deben existir en alguna otra relación (no necesariamente distinta), S; además, esos atributos también deben ser una clave candidata en S. [1] [2] [3]
En otras palabras, una clave externa es un conjunto de atributos que hace referencia a una clave candidata. Por ejemplo, una tabla llamada TEAM puede tener un atributo, MEMBER_NAME, que es una clave externa que hace referencia a una clave candidata, PERSON_NAME, en la tabla PERSON. Dado que MEMBER_NAME es una clave externa, cualquier valor que exista como el nombre de un miembro en TEAM también debe existir como el nombre de una persona en la tabla PERSON; en otras palabras, cada miembro de un TEAM también es una PERSONA.
Puntos importantes a tener en cuenta:
La tabla que contiene la clave externa se denomina tabla secundaria, y la tabla que contiene la clave candidata se denomina tabla referenciada o principal. [4] En el modelado y la implementación relacional de bases de datos, una clave candidata es un conjunto de cero o más atributos, cuyos valores se garantiza que son únicos para cada tupla (fila) en una relación. El valor o la combinación de valores de los atributos de clave candidata para cualquier tupla no se pueden duplicar para ninguna otra tupla en esa relación.
Dado que el propósito de la clave externa es identificar una fila particular de la tabla referenciada, generalmente se requiere que la clave externa sea igual a la clave candidata en alguna fila de la tabla principal, o de lo contrario no tenga valor (el valor NULL . [2] ). Esta regla se llama restricción de integridad referencial entre las dos tablas. [5] Debido a que las violaciones de estas restricciones pueden ser la fuente de muchos problemas de bases de datos, la mayoría de los sistemas de administración de bases de datos proporcionan mecanismos para garantizar que cada clave externa no nula corresponda a una fila de la tabla referenciada. [6] [7] [8]
Por ejemplo, considere una base de datos con dos tablas: una tabla CLIENTE que incluye todos los datos de los clientes y una tabla PEDIDO que incluye todos los pedidos de los clientes. Suponga que la empresa requiere que cada pedido debe hacer referencia a un solo cliente. Para reflejar esto en la base de datos, se agrega una columna de clave externa a la tabla PEDIDO (por ejemplo, CUSTOMERID), que hace referencia a la clave principal de CLIENTE (por ejemplo, ID). Debido a que la clave principal de una tabla debe ser única y debido a que CUSTOMERID solo contiene valores de ese campo de clave principal, podemos suponer que, cuando tiene un valor, CUSTOMERID identificará al cliente en particular que realizó el pedido. Sin embargo, esto ya no se puede suponer si la tabla PEDIDO no se mantiene actualizada cuando se eliminan filas de la tabla CLIENTE o se modifica la columna ID, y trabajar con estas tablas puede volverse más difícil. Muchas bases de datos del mundo real solucionan este problema "inactivando" en lugar de eliminar físicamente las claves externas de la tabla maestra, o mediante programas de actualización complejos que modifican todas las referencias a una clave externa cuando se necesita un cambio.
Las claves externas desempeñan un papel esencial en el diseño de bases de datos . Una parte importante del diseño de bases de datos es asegurarse de que las relaciones entre entidades del mundo real se reflejen en la base de datos mediante referencias, utilizando claves externas para hacer referencia de una tabla a otra. [9] Otra parte importante del diseño de bases de datos es la normalización de bases de datos , en la que las tablas se descomponen y las claves externas permiten reconstruirlas. [10]
Varias filas de la tabla de referencia (o secundaria) pueden hacer referencia a la misma fila de la tabla de referencia (o principal). En este caso, la relación entre las dos tablas se denomina relación de uno a muchos entre la tabla de referencia y la tabla de referencia.
Además, la tabla secundaria y la tabla principal pueden ser, de hecho, la misma tabla, es decir, la clave externa hace referencia a la misma tabla. Este tipo de clave externa se conoce en SQL:2003 como clave externa autorreferencial o recursiva. En los sistemas de administración de bases de datos, esto se logra a menudo vinculando una primera y una segunda referencia a la misma tabla.
Una tabla puede tener varias claves externas y cada una de ellas puede tener una tabla principal diferente. El sistema de base de datos aplica cada clave externa de forma independiente . Por lo tanto, se pueden establecer relaciones en cascada entre tablas mediante claves externas.
Una clave externa se define como un atributo o un conjunto de atributos en una relación cuyos valores coinciden con una clave principal en otra relación. La sintaxis para agregar dicha restricción a una tabla existente se define en SQL:2003 como se muestra a continuación. Omitir la lista de columnas en la REFERENCES
cláusula implica que la clave externa debe hacer referencia a la clave principal de la tabla a la que se hace referencia. Asimismo, las claves externas se pueden definir como parte de la CREATE TABLE
declaración SQL.
CREAR TABLA tabla_hija ( col1 ENTERO CLAVE PRINCIPAL , col2 CARÁCTER VARIABLE ( 20 ) , col3 ENTERO , col4 ENTERO , CLAVE EXTERNA ( col3 , col4 ) REFERENCIAS tabla_padre ( col1 , col2 ) AL ELIMINAR CASCADA )
Si la clave externa es una sola columna, la columna se puede marcar como tal utilizando la siguiente sintaxis:
CREAR TABLA tabla_hija ( col1 ENTERO CLAVE PRINCIPAL , col2 CARÁCTER VARIABLE ( 20 ), col3 ENTERO , col4 REFERENCIAS ENTERAS tabla_padre ( col1 ) AL ELIMINAR CASCADA )
Las claves externas se pueden definir con una declaración de procedimiento almacenado .
sp_foreignkey tabla_secundaria , tabla_principal , col3 , col4
Debido a que el sistema de administración de bases de datos aplica restricciones referenciales, debe garantizar la integridad de los datos si se eliminan (o actualizan) filas de una tabla referenciada. Si aún existen filas dependientes en las tablas de referencia, se deben tener en cuenta esas referencias. SQL:2003 especifica cinco acciones referenciales diferentes que se deben llevar a cabo en tales casos:
Siempre que se eliminen (o actualicen) filas de la tabla principal (a la que se hace referencia), también se eliminarán (o actualizarán) las filas respectivas de la tabla secundaria (a la que se hace referencia) con una columna de clave externa coincidente. Esto se denomina eliminación (o actualización) en cascada.
No se puede actualizar ni eliminar un valor cuando existe una fila en una tabla de referencia o secundaria que hace referencia al valor en la tabla referenciada.
De manera similar, no se puede eliminar una fila mientras exista una referencia a ella desde una tabla de referencia o secundaria.
Para entender mejor RESTRICT (y CASCADE), puede ser útil notar la siguiente diferencia, que puede no ser inmediatamente clara. La acción referencial CASCADE modifica el "comportamiento" de la tabla (secundaria) en sí misma donde se utiliza la palabra CASCADE. Por ejemplo, ON DELETE CASCADE dice efectivamente "Cuando la fila a la que se hace referencia se elimina de la otra tabla (tabla maestra), entonces elimine también de mí ". Sin embargo, la acción referencial RESTRICT modifica el "comportamiento" de la tabla maestra, no de la tabla secundaria, aunque la palabra RESTRICT aparece en la tabla secundaria y no en la tabla maestra. Por lo tanto, ON DELETE RESTRICT dice efectivamente: "Cuando alguien intenta eliminar la fila de la otra tabla (tabla maestra), evita la eliminación de esa otra tabla (y por supuesto, tampoco la eliminas de mí, pero ese no es el punto principal aquí)".
RESTRICT no es compatible con Microsoft SQL 2012 y versiones anteriores.
NO ACTION y RESTRICT son muy similares. La principal diferencia entre NO ACTION y RESTRICT es que con NO ACTION la comprobación de integridad referencial se realiza después de intentar modificar la tabla. RESTRICT realiza la comprobación antes de intentar ejecutar la instrucción UPDATE o DELETE . Ambas acciones referenciales actúan de la misma manera si la comprobación de integridad referencial falla: la instrucción UPDATE o DELETE generará un error.
En otras palabras, cuando se ejecuta una sentencia UPDATE o DELETE en la tabla referenciada utilizando la acción referencial NO ACTION, el DBMS verifica al final de la ejecución de la sentencia que no se viole ninguna de las relaciones referenciales. Esto es diferente de RESTRICT, que supone desde el principio que la operación violará la restricción. Al utilizar NO ACTION, los desencadenadores o la semántica de la sentencia en sí pueden producir un estado final en el que no se violen relaciones de clave externa en el momento en que se verifique finalmente la restricción, lo que permite que la sentencia se complete correctamente.
En general, la acción tomada por el DBMS para SET NULL o SET DEFAULT es la misma para ON DELETE o ON UPDATE: el valor de los atributos de referencia afectados se cambia a NULL para SET NULL y al valor predeterminado especificado para SET DEFAULT.
Las acciones referenciales generalmente se implementan como activadores implícitos (es decir, activadores con nombres generados por el sistema, a menudo ocultos). Como tales, están sujetos a las mismas limitaciones que los activadores definidos por el usuario, y puede ser necesario considerar su orden de ejecución en relación con otros activadores; en algunos casos, puede resultar necesario reemplazar la acción referencial con su activador definido por el usuario equivalente para garantizar el orden de ejecución adecuado o para solucionar las limitaciones de la tabla de mutaciones.
Otra limitación importante aparece con el aislamiento de transacciones : sus cambios en una fila pueden no poder aplicarse en cascada completamente porque la fila está referenciada por datos que su transacción no puede "ver" y, por lo tanto, no puede aplicarse en cascada. Un ejemplo: mientras su transacción está intentando renumerar una cuenta de cliente, una transacción simultánea está intentando crear una nueva factura para ese mismo cliente; mientras que una regla CASCADE puede arreglar todas las filas de facturas que su transacción puede ver para mantenerlas consistentes con la fila del cliente renumerada, no llegará a otra transacción para arreglar los datos allí; debido a que la base de datos no puede garantizar datos consistentes cuando las dos transacciones se confirman, una de ellas se verá obligada a revertir (a menudo por orden de llegada).
CREAR TABLA cuenta ( num_cuenta INT , monto DECIMAL ( 10 , 2 )); CREAR DISPARADOR ins_sum ANTES DE INSERTAR EN cuenta PARA CADA FILA ESTABLECIDA @ suma = @ suma + NUEVO . monto ;
Como primer ejemplo para ilustrar las claves externas, supongamos que una base de datos de cuentas tiene una tabla con facturas y cada factura está asociada a un proveedor en particular. Los detalles del proveedor (como el nombre y la dirección) se guardan en una tabla separada; a cada proveedor se le asigna un "número de proveedor" para identificarlo. Cada registro de factura tiene un atributo que contiene el número de proveedor para esa factura. Entonces, el "número de proveedor" es la clave principal en la tabla de proveedores. La clave externa en la tabla de facturas apunta a esa clave principal. El esquema relacional es el siguiente. Las claves principales están marcadas en negrita y las claves externas están marcadas en cursiva.
Proveedor ( Número de proveedor , Nombre, Dirección) Factura ( Número de factura , Texto, Número de proveedor )
La declaración del lenguaje de definición de datos correspondiente es la siguiente.
CREAR TABLA Proveedor ( NúmeroProveedor ENTERO NOT NULL , Nombre VARCHAR ( 20 ) NOT NULL , Dirección VARCHAR ( 50 ) NOT NULL , RESTRICCIÓN proveedor_pk CLAVE PRIMARIA ( NúmeroProveedor ), RESTRICCIÓN número_valor VERIFICAR ( NúmeroProveedor > 0 ) ) CREAR TABLA Factura ( NúmeroFactura ENTERO NO NULO , Texto VARCHAR ( 4096 ), NúmeroProveedor ENTERO NO NULO , RESTRICCIÓN factura_pk CLAVE PRIMARIA ( NúmeroFactura ), RESTRICCIÓN inumber_value COMPROBAR ( NúmeroFactura > 0 ), RESTRICCIÓN proveedor_fk CLAVE EXTERNA ( NúmeroProveedor ) REFERENCIAS Proveedor ( NúmeroProveedor ) AL ACTUALIZAR CASCADA AL ELIMINAR RESTRINGIR )