我正在使用mysql 5.6.20并且我有以下架构:
项目活动表:
CREATE TABLE `prj_project_activity_detail` (
`fkPrjProjectActivity` VARCHAR(128) NOT NULL,
`fkPrjProjectActivitySub` VARCHAR(128) NOT NULL,
`fkProjectId` INT(10) UNSIGNED NOT NULL,
PRIMARY KEY (`fkPrjProjectActivity`, `fkPrjProjectActivitySub`, `fkProjectId`),
INDEX `FK__prj_project_activity` (`fkPrjProjectActivity`, `fkProjectId`),
INDEX `FK__prj_project_activity_2` (`fkPrjProjectActivitySub`, `fkProjectId`),
CONSTRAINT `FK__prj_project_activity` FOREIGN KEY (`fkPrjProjectActivity`, `fkProjectId`) REFERENCES `prj_project_activity` (`PrjProjectActivity`, `fkProjectId`) ON UPDATE CASCADE,
CONSTRAINT `FK__prj_project_activity_2` FOREIGN KEY (`fkPrjProjectActivitySub`, `fkProjectId`) REFERENCES `prj_project_activity` (`PrjProjectActivity`, `fkProjectId`) ON UPDATE CASCADE
)
COLLATE='utf8_general_ci'
ENGINE=InnoDB;
数据:
fkPrjProjectActivity fkPrjProjectActivitySub fkProjectId
Activity 1 Sub Activity 1 1
Activity 1 Sub Activity 2 1
Activity 1 Sub Activity 3 1
交易表:
CREATE TABLE `str_transaction` (
`StrTransactionId` VARCHAR(32) NOT NULL,
`fkPrjProjectActivity` VARCHAR(128) NULL DEFAULT NULL,
`fkPrjProjectActivitySub` VARCHAR(128) NULL DEFAULT NULL,
`fkProjectId` INT(10) UNSIGNED NULL DEFAULT NULL,
PRIMARY KEY (`StrTransactionId`),
INDEX `FK_str_transaction_department` (`fkTransactionForStoreDepartmentId`),
INDEX `FK_str_transaction_prj_project_activity_detail` (`fkPrjProjectActivity`, `fkPrjProjectActivitySub`, `fkProjectId`),
CONSTRAINT `FK_str_transaction_prj_project_activity_detail` FOREIGN KEY (`fkPrjProjectActivity`, `fkPrjProjectActivitySub`, `fkProjectId`) REFERENCES `prj_project_activity_detail` (`fkPrjProjectActivity`, `fkPrjProjectActivitySub`, `fkProjectId`) ON UPDATE CASCADE,
)
COLLATE='utf8_general_ci'
ENGINE=InnoDB;
预期执行数据:
StrTransactionId fkPrjProjectActivity fkPrjProjectActivitySub fkProjectId
1 Activity 1 Sub Activity 2 1
2 Activity 1 Sub Activity 3 1
但它允许我插入如下所示的任何数据:
意外结果:
StrTransactionId fkPrjProjectActivity fkPrjProjectActivitySub fkProjectId
1 Dummy 1 Sub Activity 2 (NULL)
2 Activity 1 (NULL) 1
3 Dummy 1 Dummy 1 (NULL)
奇怪的是,它甚至接受不在父表中的数据。
只有当所有列都包含数据时,外国关键约束才会受到影响吗?
如果任何列包含数据或所有列必须为NULL,我想强制执行约束。
Mysql Doc。说,(link)
SQL标准中的MATCH子句控制a中NULL值的方式 比较时处理复合(多列)外键 主键。 MySQL本质上实现了定义的语义 MATCH SIMPLE,允许外键全部或部分为NULL。 在这种情况下,包含这样的外键的(子表)行是 允许插入,并且与引用的任何行都不匹配 (父)表。可以使用实现其他语义 触发器。
我不能将“NOT NULL”作为基本要求。我在str_transaction
表中有许多其他字段(与问题无关)在此处删除,以便更清楚地说明问题。
按照文档中的建议实施触发器是一种好习惯吗?或者任何人都可以帮我设计架构吗?
答案 0 :(得分:0)
像eggyal建议的那样,我会为prj_project_activity_detail
表创建一个自动增量主键,并为引用它的str_transaction
表创建一个外键。
结构可能如下:
CREATE TABLE `prj_project_activity_detail` (
`prjProjectActivityDetailId` INT(10) UNSIGNED NOT NULL AUTO_INCREMENT,
`fkPrjProjectActivity` VARCHAR(128) NOT NULL,
`fkPrjProjectActivitySub` VARCHAR(128) NOT NULL,
`fkProjectId` INT(10) UNSIGNED NOT NULL,
PRIMARY KEY (`prjProjectActivityDetailId`),
INDEX `FK__prj_project_activity` (`fkPrjProjectActivity`, `fkProjectId`),
INDEX `FK__prj_project_activity_2` (`fkPrjProjectActivitySub`, `fkProjectId`),
CONSTRAINT `FK__prj_project_activity` FOREIGN KEY (`fkPrjProjectActivity`, `fkProjectId`) REFERENCES `prj_project_activity` (`PrjProjectActivity`, `fkProjectId`) ON UPDATE CASCADE,
CONSTRAINT `FK__prj_project_activity_2` FOREIGN KEY (`fkPrjProjectActivitySub`, `fkProjectId`) REFERENCES `prj_project_activity` (`PrjProjectActivity`, `fkProjectId`) ON UPDATE CASCADE
)
COLLATE='utf8_general_ci'
ENGINE=InnoDB;
CREATE TABLE `str_transaction` (
`StrTransactionId` VARCHAR(32) NOT NULL,
`fkPrjProjectActivityDetailId` INT(10) UNSIGNED NULL DEFAULT NULL,
PRIMARY KEY (`StrTransactionId`),
INDEX `FK_str_transaction_prj_project_activity_detail` (`fkPrjProjectActivityDetailId`),
CONSTRAINT `FK_str_transaction_prj_project_activity_detail` FOREIGN KEY (`fkPrjProjectActivityDetailId`) REFERENCES `prj_project_activity_detail` (`prjProjectActivityDetailId`) ON UPDATE CASCADE
)
COLLATE='utf8_general_ci'
ENGINE=InnoDB;
现在,您无法在示例中插入无效数据,因为您的foregn键是现有的prjProjectActivityDetailId
或NULL
。
要模拟旧的str_transaction
表,您可以使用左连接创建视图:
CREATE VIEW `str_transaction_view` AS
SELECT
st.StrTransactionId,
pad.fkPrjProjectActivity,
pad.fkPrjProjectActivitySub,
pad.fkProjectId
FROM str_transaction st
LEFT JOIN prj_project_activity_detail pad
ON pad.prjProjectActivityDetailId = st.fkPrjProjectActivityDetailId;