¿Pueden las columnas de tabla con una clave foránea ser null?


Por ejemplo, tengo una tabla que tiene varias columnas ID a otras tablas. Quiero una clave foránea para forzar la integridad solo si pongo datos allí. Si hago una actualización en un momento posterior para rellenar esa columna, todavía comprobará la restricción (esto es probablemente dependiente del servidor de base de datos, estoy usando el tipo de tabla MySQL & InnoDB). Creo que esta es una expectativa razonable, pero corrígeme si me equivoco.

Author: Daniel Vassallo, 2010-03-03

3 answers

Sí, puede aplicar la restricción solo cuando el valor no es NULL. Esto se puede probar 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`))

El primer insert pasará porque insertamos un NULL en el parent_id. La segunda inserción falla debido a la restricción de clave foránea, ya que intentamos insertar un valor que no existe en la tabla parent.

 159
Author: Daniel Vassallo,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-09-22 13:36:02

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

 18
Author: Backslider,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2012-12-19 07:25:29

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

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

 2
Author: davidtbernal,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2010-03-02 21:38:49