我有一个包含两个字段的表,一个可空,一个不可空。这些字段构成此表的复合唯一键
CREATE TABLE `sections` (
`product_id` varchar(255) NULL DEFAULT NULL,
`id` varchar(255) NOT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
ALTER TABLE `sections`
ADD UNIQUE KEY (`product_id`, `id`);
我有另一个表,在第一个表的唯一键字段上有外键约束
CREATE TABLE `sections_t` (
`product_id` varchar(255) NULL DEFAULT NULL,
`section_id` varchar(255) NOT NULL,
`name` varchar(255) NOT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
ALTER TABLE `sections_t`
ADD CONSTRAINT `sections_t_ibfk_1` FOREIGN KEY (`product_id`, `section_id`) REFERENCES `sections` (`product_id`, `id`) ON DELETE CASCADE ON UPDATE CASCADE;
当我在sections
表上更新/删除product_id
not null的条目时,一切似乎都能正常工作。但是当我更新/删除具有product_id
null的条目时,更改不会级联到sections_t
。
如何级联包含空字段的条目的更改?
您不应该有一个引用可空字段的FK(外键)。这不是标准的SQL和MySQL让你用InnoDB,但tells you not to:
对于诸如UPDATE或DELETE CASCADE之类的操作,没有很好地定义对非唯一键或包含NULL值的键的外键引用的处理。建议您使用只引用UNIQUE(或PRIMARY)和NOT NULL的键的外键。
但SQL实际上并不是为了支持带有NULL作为标识符的子行:
您是否理解在默认和通常且通常仅实现(包括在MySQL)模式下的FK匹配是,如果任何FK列为NULL,则无论引用表中的内容是什么,都认为FK约束是否满足? (并且在没有模式下,NULL FK列值与引用表中的任何内容匹配?)因此,即使您使用MySQL功能,也永远不会与表单的FK匹配(x,NULL)?
(你是否理解,在SQL NULL <> NULL的精神下,如果一个带有NULL的FK子行必须在其引用的表中具有相同的值,那么它永远不会,因为引用的表中的任何内容都不能等于该NULL,即使是空值?)
您是否了解没有NULL的UNIQUE索引定义允许表中任何形式的行(p,NULL)? (它在变态的SQL 3VL方式中只是“唯一的”。)那么具有可空列的UNIQUE是否真正捕获了您在引用表中所需的约束?
你是否理解查询会很复杂,因为如果手动想要(x,NULL)对包含的(x,NULL)对,你必须编写像OR id IS NULL这样的东西吗?
如果您需要这些表,则必须为约束和级联编写触发器。但是您应该使用按照SQL期望和支持的方式使用NULL的设计。这仍然可能涉及一些触发器,但您可能会使用一些声明性约束和级联,并且您的设计在SQL使用方面不会是非标准和反直觉的。