假设,我有一个名为 Category
的 ENUM
列和一个名为 Subcategory
的 ENUM
列。有时我会想单独在 Category
上SELECT
,这就是它们被分开的原因。
CREATE TABLE `Bonza` (
`EventId` INT UNSIGNED NOT NULL AUTO_INCREMENT,
`Category` ENUM("a", "b", "c") NOT NULL,
`Subcategory` ENUM("x", "y", "z") NOT NULL,
PRIMARY KEY(`EventId`)
) ENGINE=InnoDB;
但并非所有子类别都适用于所有类别(例如,"z"
仅对 "a"
和 "b"
有效), 令我恼火的是,这个约束没有融入表格的设计中。如果 MySQL 具有某种“对”类型(其中该类型的列可在值的前导子序列上建立索引),那么这就不是问题。
如果我想保持类别和子类别之间的完整性,我就不得不在触发器中编写长条件语句。还是我最好离开它?你会怎么做?
我认为最面向关系的方法是存储一个 EventCategoryId
,并将其映射到一个包含所有有效事件类型对的表,并在每次我想查找时加入该表事件类别的含义。
CREATE TABLE `Bonza` (
`EventId` INT UNSIGNED NOT NULL AUTO_INCREMENT,
`EventCategoryId` INT UNSIGNED NOT NULL,
PRIMARY KEY(`EventId`),
FOREIGN KEY `EventCategoryId` REFEFRENCES(`EventCategories`.`EventCategoryId`)
ON DELETE RESTRICT ON UPDATE CASCADE
) ENGINE=InnoDB;
CREATE TABLE `EventCategories` (
`EventCategoryId` INT UNSIGNED NOT NULL,
`Category` ENUM("a", "b", "c") NOT NULL,
`Subcategory` ENUM("x", "y", "z") NOT NULL,
PRIMARY KEY(`EventCategoryId`)
) ENGINE=InnoDB;
-- Now populate this table with valid category/subcategory pairs at installation
我可以做更简单的事情吗?对于 INSERT
到 Bonza
中,此查找可能会降低调用代码的复杂性和性能,不是吗?
最佳答案
假设您的类别和子类别不会经常更改,并且假设您愿意接受重大更新,那么您可以执行以下操作:
使用EventCategories
表来控制类别和子类别之间的层次约束。该表的主键应该是包含类别
和子类别
的复合键。在您的 Bonza
表中引用此表。 Bonza
中的外键恰好包含您要作为筛选依据的两列,因此您无需加入即可获得所需内容。也不可能分配无效的组合。
CREATE TABLE `Bonza` (
`EventId` UNSIGNED INT NOT NULL AUTO_INCREMENT,
`Category` CHAR(1) NOT NULL,
`Subcategory` CHAR(1) NOT NULL,
PRIMARY KEY(`EventId`),
FOREIGN KEY `Category`, `Subcategory`
REFEFRENCES(`EventCategories`.`Category`, `EventCategories`.`Subcategory`)
ON DELETE RESTRICT ON UPDATE CASCADE
) ENGINE=InnoDB;
CREATE TABLE `EventCategories` (
`EventCategoryId` UNSIGNED INT NOT NULL,
`Category` CHAR(1) NOT NULL,
`Subcategory` CHAR(1) NOT NULL,
PRIMARY KEY(`Category`, `Subcategory`)
) ENGINE=InnoDB;
关于mysql - 我怎样才能最好地保持表中两列之间的完整性?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/22711747/