¿Pueden las columnas de la tabla con una clave externa ser NULL?

Resuelto bender asked hace 14 años • 7 respuestas

Tengo una tabla que tiene varias columnas de ID de otras tablas.

Quiero una clave externa para forzar la integridad sólo si pongo datos allí. Si hago una actualización más adelante para completar esa columna, entonces también debería verificar la restricción.

(Esto probablemente depende del servidor de la base de datos, estoy usando el tipo de tabla MySQL e InnoDB)

Creo que esta es una expectativa razonable, pero corríjanme si me equivoco.

bender avatar Mar 03 '10 04:03 bender
Aceptado

Sí, puede aplicar la restricción solo cuando el valor no sea NULL. Esto se puede comprobar fácilmente con el siguiente ejemplo:

CREATE DATABASE t;
USE t;

CREATE TABLE parent (id INT NOT NULL,
                     PRIMARY KEY (id)
) ENGINE=INNODB;

CREATE TABLE child (id INT NULL, 
                    parent_id INT NULL,
                    FOREIGN KEY (parent_id) REFERENCES parent(id)
) ENGINE=INNODB;


INSERT INTO child (id, parent_id) VALUES (1, NULL);
-- Query OK, 1 row affected (0.01 sec)


INSERT INTO child (id, parent_id) VALUES (2, 1);

-- ERROR 1452 (23000): Cannot add or update a child row: a foreign key 
-- constraint fails (`t/child`, CONSTRAINT `child_ibfk_1` FOREIGN KEY
-- (`parent_id`) REFERENCES `parent` (`id`))

La primera inserción pasará porque insertamos un NULL en el archivo parent_id. La segunda inserción falla debido a la restricción de clave externa, ya que intentamos insertar un valor que no existe en la parenttabla.

Daniel Vassallo avatar Mar 02 '2010 21:03 Daniel Vassallo

Descubrí que al insertar, los valores de la columna nula debían declararse específicamente como NULL; de lo contrario, obtendría un error de infracción de restricción (en lugar de una cadena vacía).

Backslider avatar Dec 19 '2012 07:12 Backslider

Sí, eso funcionará como esperas. Desafortunadamente, parece que tengo problemas para encontrar una declaración explícita de esto en el manual de MySQL .

Las claves externas significan que el valor debe existir en la otra tabla. NULL se refiere a la ausencia de valor, por lo que cuando establece una columna en NULL, no tendría sentido intentar imponer restricciones a eso.

davidtbernal avatar Mar 02 '2010 21:03 davidtbernal

Sí, el valor puede ser NULL, pero debes ser explícito. He experimentado esta misma situación antes y es fácil olvidar POR QUÉ sucede esto, por lo que lleva un poco de tiempo recordar lo que se debe hacer.

Si los datos enviados se convierten o interpretan como una cadena vacía, fallará. Sin embargo, al establecer explícitamente el valor en NULL al INSERTAR o ACTUALIZAR, estará listo.

Pero esto es lo divertido de programar, ¿no? ¡Creando nuestros propios problemas y luego solucionándolos! ¡Salud!

Toby Crain avatar Sep 25 '2019 18:09 Toby Crain