¿Puede una clave foránea ser NULL y / o duplicarse?

325

Por favor aclara dos cosas para mí:

  1. ¿Puede una clave externa ser NULL?
  2. ¿Se puede duplicar una clave externa?

Por lo que sé, NULLno debería usarse en claves externas, pero en algunas aplicaciones mías puedo ingresar NULLtanto en Oracle como en SQL Server, y no sé por qué.

Enjambres
fuente
1
@ Adrian: Lo mejor de mi conocimiento es que la clave externa no puede ser nula, pero se está volviendo nula en el servidor SQL y Oracle. ¿puedes explicar porque?
atasca
@Jams - lee el enlace en mi respuesta.
JNK
11
esto no se puede eliminar porque las respuestas y la pregunta son útiles. Siéntase libre de editar la pregunta para mejorarla.
Jeff Atwood
Dividir la pregunta sobre duplicados. A continuación, solo se responde a la pregunta sobre NULL.
reinierpost

Respuestas:

529

Respuesta corta: Sí, puede ser NULL o duplicado.

Quiero explicar por qué una clave externa puede ser nula o ser única o no única. Primero recuerde que una clave externa simplemente requiere que el valor en ese campo debe existir primero en una tabla diferente (la tabla principal). Eso es todo un FK es por definición. Nulo por definición no es un valor. Nulo significa que aún no sabemos cuál es el valor.

Déjame darte un ejemplo de la vida real. Supongamos que tiene una base de datos que almacena propuestas de ventas. Supongamos además que cada propuesta solo tiene un vendedor asignado y un cliente. Por lo tanto, su tabla de propuesta tendría dos claves foráneas, una con la ID del cliente y otra con la ID del representante de ventas. Sin embargo, en el momento en que se crea el registro, no siempre se asigna un representante de ventas (porque todavía no hay nadie libre para trabajar en él), por lo que la ID del cliente se completa pero la ID del representante de ventas puede ser nula. En otras palabras, generalmente necesita la capacidad de tener un FK nulo cuando puede no conocer su valor en el momento en que se ingresan los datos, pero sí conoce otros valores en la tabla que deben ingresarse. Para permitir nulos en un FK, generalmente todo lo que tiene que hacer es permitir nulos en el campo que tiene el FK. El valor nulo está separado de la idea de que sea un FK.

Si es único o no único se relaciona con si la tabla tiene una relación uno-uno o uno-muchos con la tabla principal. Ahora, si tiene una relación uno a uno, es posible que pueda tener todos los datos en una tabla, pero si la tabla se está ampliando demasiado o si los datos están en un tema diferente (el empleado - ejemplo de seguro @tbone dio por ejemplo), entonces quieres tablas separadas con un FK. Entonces querrá hacer que este FK sea también el PK (que garantiza la unicidad) o imponerle una restricción única.

La mayoría de las FK son para una relación de uno a muchos y eso es lo que obtienes de una FK sin agregar una restricción adicional en el campo. Por lo tanto, tiene una tabla de pedidos y la tabla de detalles del pedido, por ejemplo. Si el cliente ordena diez artículos a la vez, tiene un pedido y diez registros detallados que contienen el mismo ID de pedido que el FK.

HLGEM
fuente
13
Entonces, ¿eso es mejor que tener un vendedor falso llamado "Sin asignar"?
Thomas Weller
8
Un comentario. Los nulos dejan mucho espacio para errores en la consulta de personas que no saben cómo SQL (mis) maneja 3VL. Si un vendedor no es realmente necesario para una determinada tabla r, simplemente no incluya ese registro. Una tabla separada puede ser "ProposalAssignedTo" o algo así, con las restricciones apropiadas. Un escritor de consultas puede unirse a esa tabla y proporcionar su propia lógica para lo que queramos hacer cuando una propuesta no tiene un vendedor. NULL no sólo significa "no sabemos" - que puede ser utilizado para muchas cosas (que es por eso que es casi siempre una mala idea)
N West
26
@nWest, no permito que las personas incompetentes consulten mis bases de datos y cualquier desarrollador que no sepa cómo manejar los valores nulos es incompetente. Hay momentos en que los datos no se conocen en el momento de la entrada de datos inicial para un campo en particular, pero los otros campos son necesarios en ese momento.
HLGEM
28
@ThomasWeller Hacer referencia a un vendedor falso ("Sin asignar") empeora el problema. Supongo que su mesa de vendedor tiene varias columnas ...? ¿Cuál es el número de seguro social del Sr. No asignado? ¿A qué departamento está asignado? Quien es su jefe Espero que entiendas mi punto: cuando creas un vendedor "no asignado", descubres rápidamente que cambiaste NULLen una tabla por varios correos NULLelectrónicos en una tabla diferente.
Gili
1
@ThomasWeller También tendrá un problema si / cuando necesite localizar su interfaz.
tobiv
45

De la boca del caballo:

Las claves externas permiten valores de clave que son todos NULL, incluso si no hay claves PRIMARY o UNIQUE coincidentes

Sin restricciones en la clave externa

Cuando no se definen otras restricciones en la clave externa, cualquier número de filas en la tabla secundaria puede hacer referencia al mismo valor de clave principal. Este modelo permite nulos en la clave foránea. ...

Restricción NOT NULL en la clave externa

Cuando no se permiten nulos en una clave externa, cada fila de la tabla secundaria debe hacer referencia explícitamente a un valor en la clave principal porque los nulos no están permitidos en la clave externa.

Cualquier número de filas en la tabla secundaria puede hacer referencia al mismo valor de clave principal, por lo que este modelo establece una relación de uno a muchos entre las claves principal y externa. Sin embargo, cada fila de la tabla secundaria debe tener una referencia a un valor de clave principal; No se permite la ausencia de un valor (nulo) en la clave externa. El mismo ejemplo en la sección anterior puede usarse para ilustrar tal relación. Sin embargo, en este caso, los empleados deben tener una referencia a un departamento específico.

Restricción ÚNICA en la clave externa

Cuando se define una restricción ÚNICA en la clave externa, solo una fila de la tabla secundaria puede hacer referencia a un valor de clave principal determinado. Este modelo permite nulos en la clave foránea.

Este modelo establece una relación uno a uno entre las claves principal y externa que permite valores indeterminados (nulos) en la clave externa. Por ejemplo, suponga que la tabla de empleados tenía una columna llamada MEMBERNO, que se refiere a un número de miembro de empleado en el plan de seguro de la compañía. Además, una tabla llamada INSURANCE tiene una clave principal llamada MEMBERNO, y otras columnas de la tabla mantienen la información respectiva relacionada con la póliza de seguro de un empleado. El MEMBERNO en la tabla de empleados debe ser una clave externa y una clave única:

  • Para imponer reglas de integridad referencial entre las tablas EMP_TAB y INSURANCE (la restricción FOREIGN KEY)

  • Para garantizar que cada empleado tenga un número de membresía único (la restricción de clave ÚNICA)

Restricciones ÚNICAS y NO NULAS en la clave externa

Cuando se definen restricciones ÚNICAS y NO NULAS en la clave externa, solo una fila en la tabla secundaria puede hacer referencia a un valor de clave principal dado, y dado que los valores NULL no están permitidos en la clave externa, cada fila en la tabla secundaria debe hacer referencia explícitamente Un valor en la clave principal.

Mira esto:

Enlace Oracle 11g

tbone
fuente
16

Sí, la clave foránea puede ser nula como se indicó anteriormente por los programadores senior ... Agregaría otro escenario donde la clave foránea deberá ser nula ... supongamos que tenemos tablas de comentarios, imágenes y videos en una aplicación que permite comentarios sobre imágenes y videos En la tabla de comentarios podemos tener dos claves extranjeras PicturesId, y VideosId junto con la clave primaria CommentId. Entonces, cuando comentas en un video solo se requerirá VideosId y pictureId sería nulo ... y si comentas solo en una foto, se requeriría PictureId y VideosId sería nulo ...

Touseef Ahmed Awan
fuente
1
Creo que hay una mejor manera de resolver este problema. En lugar de crear nuevas columnas, puede tener dos columnas, a saber, "id" y "type", que contendrán el id y el nombre de la tabla de claves foráneas. Por ejemplo, id = 1, type = Picture representará un enlace a la tabla Picture con id 1. La ventaja de usar esta solución es que no tendrá que crear nuevas columnas cuando se agreguen comentarios a tablas adicionales. La desventaja no será una restricción de clave externa en el nivel de base de datos, sino que la restricción tendrá que ser el nivel de la aplicación.
Agent47DarkSoul
44
@Agent: Hemos tenido esta "solución" en el uso de producción. No lo hagas, es terrible. Hacer consultas se convierte en este lío de "si es de tipo 1, únete a esta tabla, de lo contrario únete a esto". Fue una pesadilla para nosotros. Terminamos haciendo lo que dice esta respuesta y creamos una nueva columna para cada tipo de unión. Crear columnas es barato. Prácticamente su único defecto es que muchas columnas hacen que Toad sea difícil de usar, pero eso es solo un defecto de Toad.
user128216
1
@FighterJet Rails proporciona un gran marco ORM que maneja incluso consultas complejas con esta solución.
Agent47DarkSoul
2
@Agent: Tal vez pueda ... pero si puedes hacerlo simple, ¿por qué hacerlo complejo? Y tal vez "pesadilla" era la palabra incorrecta para usar: era muy inconveniente. No sufrimos problemas de integridad de datos (mucho).
user128216
7

depende de qué papel foreign keyjuega esto en su relación.

  1. si esto foreign keytambién está key attributeen su relación, entonces no puede ser NULL
  2. Si este foreign keyes un atributo normal en su relación, puede ser NULL.
shinxg
fuente
3

Aquí hay un ejemplo usando la sintaxis de Oracle:
Primero creemos una tabla COUNTRY

CREATE TABLE TBL_COUNTRY ( COUNTRY_ID VARCHAR2 (50) NOT NULL ) ;
ALTER TABLE TBL_COUNTRY ADD CONSTRAINT COUNTRY_PK PRIMARY KEY ( COUNTRY_ID ) ;

Crea la tabla PROVINCIA

CREATE TABLE TBL_PROVINCE(
PROVINCE_ID VARCHAR2 (50) NOT NULL ,
COUNTRY_ID  VARCHAR2 (50)
);
ALTER TABLE TBL_PROVINCE ADD CONSTRAINT PROVINCE_PK PRIMARY KEY ( PROVINCE_ID ) ;
ALTER TABLE TBL_PROVINCE ADD CONSTRAINT PROVINCE_COUNTRY_FK FOREIGN KEY ( COUNTRY_ID ) REFERENCES TBL_COUNTRY ( COUNTRY_ID ) ;

Esto funciona perfectamente bien en Oracle. Observe que la clave externa COUNTRY_ID en la segunda tabla no tiene "NOT NULL".

Ahora, para insertar una fila en la tabla PROVINCE, es suficiente especificar solo PROVINCE_ID. Sin embargo, si elige especificar un COUNTRY_ID también, debe existir en la tabla COUNTRY.

Mouhcine
fuente
1

Por defecto no hay restricciones en la clave externa, la clave externa puede ser nula y duplicada.

mientras crea una tabla / modifica la tabla, si agrega alguna restricción de unicidad o no nula, entonces solo no permitirá los valores nulos / duplicados.

nitin lalwani
fuente
0

En pocas palabras, las relaciones "no identificables" entre entidades forman parte del modelo ER y están disponibles en Microsoft Visio cuando se diseña el diagrama ER. Esto es necesario para imponer la cardinalidad entre entidades de tipo "cero o más que cero" o "cero o uno". Tenga en cuenta este "cero" en cardinalidad en lugar de "uno" en "uno a muchos".

Ahora, un ejemplo de relación no identificable donde la cardinalidad puede ser "cero" (no identificable) es cuando decimos que un registro / objeto en una entidad-A "puede" o "no puede" tener un valor como referencia para el registro / s en otra Entidad-B.

Como existe la posibilidad de que un registro de la entidad-A se identifique con los registros de otra Entidad-B, por lo tanto, debe haber una columna en la Entidad-B para tener el valor de identidad del registro de la Entidad-B. Esta columna puede ser "Nula" si ningún registro en la Entidad-A identifica el / los registro / s (u objeto / s) en la Entidad-B.

En el Paradigma orientado a objetos (mundo real), hay situaciones en las que un objeto de Clase B no necesariamente depende (fuertemente acoplado) del objeto de clase A para su existencia, lo que significa que la Clase B está débilmente acoplada con Clase- A tal que la Clase A pueda "Contener" (Contención) un objeto de la Clase A, en oposición al concepto de objeto de la Clase B debe tener (Composición) un objeto de la Clase A, para su (objeto de clase- B) creación.

Desde el punto de vista de la consulta SQL, puede consultar todos los registros en la entidad-B que "no son nulos" para la clave externa reservada para la entidad-B. Esto traerá todos los registros que tengan cierto valor correspondiente para las filas en la Entidad-A alternativamente, todos los registros con valor Nulo serán los registros que no tienen ningún registro en la Entidad-A en la Entidad-B.

Fakhar
fuente
-1

Creo que es mejor considerar la posible cardinalidad que tenemos en las tablas. Podemos tener una cardinalidad mínima posible cero. Cuando es opcional, la participación mínima de tuplas de la tabla relacionada podría ser cero. Ahora se enfrenta a la necesidad de que los valores de clave externa sean nulos.

Pero la respuesta es que todo depende del negocio.

usuario9274383
fuente
-3

La idea de una clave externa se basa en el concepto de hacer referencia a un valor que ya existe en la tabla principal. Es por eso que se llama una clave foránea en la otra tabla. Este concepto se llama integridad referencial. Si una clave externa se declara como un campo nulo, violará la lógica misma de la integridad referencial. ¿A qué se referirá? Solo puede referirse a algo que está presente en la tabla principal. Por lo tanto, creo que sería incorrecto declarar un campo de clave externa como nulo.

SQLDev
fuente
Puede hacer referencia a "nada" o aún no conoce su valor NULL, pero lo que dice la integridad referencial es que si hace referencia a "algo", debe estar allí.
yaxe
-7

Creo que la clave externa de una tabla también es la clave principal de otra tabla, por lo que no permite valores nulos, por lo que no se trata de tener un valor nulo en la clave externa.

usuario4532553
fuente