以编程方式确定哪个FOREIGN KEY约束失败

时间:2014-11-26 17:03:25

标签: php mysql foreign-keys

因此,假设以下(简化)设置:

CREATE TABLE Table1(
  `a` int PRIMARY KEY
) ENGINE=INNODB;

INSERT INTO Table1 (`a`) VALUES (1),(2),(3);

CREATE TABLE Table2(
  `a` int,
  FOREIGN KEY (`a`) REFERENCES Table1(`a`) ON DELETE CASCADE
) ENGINE=INNODB;

我们有两个表,其中第二个表有一个外键引用第一个。

如果我执行类似

的内容
INSERT INTO `Table2` VALUES ( 1 );
一切都很好。但是如果我执行

INSERT INTO `Table2` VALUES ( 5 );

我收到类似

的错误消息
  

#1452 - 无法添加或更新子行:外键约束失败(table2,CONSTRAINT table2_ibfk_1 FOREIGN KEY(a)REFERENCES table1({{ 1}})ON DELETE CASCADE)

这是正确的。

只要我只有一个外键,就可以看到,这是失败的。但进一步假设我有多个外键约束:

如何在PHP中以编程方式确定哪些失败?

我能想到的唯一方法是解析错误字符串并尝试提取相应的列,但如果MySQL决定更改其错误消息的语法,则这非常不稳定。


一些背景知识:有一个基础数据模型,如star-schema,它只是在数据库中表示。我不想检查PHP中的所有约束,因为这将要求从数据库中删除大量数据(外键的可能值列表相当长)或者激活大量查询以查看,如果值存在于各自的维度表中。两者似乎都不是一个好方法。特别是因为MySQL无论如何都要检查这些约束。

2 个答案:

答案 0 :(得分:3)

最简单的方法是命名约束:

CREATE TABLE Table2(
  `a` int,
  CONSTRAINT FK_table2_a FOREIGN KEY (`a`) REFERENCES Table1(`a`) ON DELETE CASCADE
) ENGINE=INNODB;

然后错误消息会说出可理解的内容。

答案 1 :(得分:0)

您唯一关心的是找出INSERT是否会失败。不确定你认为它会有多高效,但你可以 在表上定义BEFORE INSERT触发器并让触发器发出特定的警告消息或在错误日志表中记录该消息。像(一个粗略的想法)

的东西
DELIMITER $$
CREATE TRIGGER `test_before_insert` BEFORE INSERT ON `Table2`
FOR EACH ROW
BEGIN
DECLARE @row_count INT;
SELECT COUNT(*) INTO @row_count FROM Table1 WHERE `a` = NEW.a;
    IF @row_count <= 0 THEN
      INSERT INTO Error_Log(`detail`, `value`)
      VALUES('Insert failed for value ', NEW.a);
    END IF;
END$$   
DELIMITER ; 

然后,如果a插入操作的某些值完全失败,那么您可以确保在Error_Log表中可以获得相同的信息;它可以直接从您的应用程序代码(PHP)中获取。