sql删除外键约束

时间:2014-09-13 04:08:54

标签: mysql sql

我有三个表,其中一个是关系表,例如:

有主键: peopleid ;
宠物有主键: petid ;
拥有有两个外键: peopleid petid ,它们一起作为表自己 <的主键/ p>

现在
我试图从表格中删除一个人 peopleid ,同时,应该删除此人拥有的宠物,以及存储在表格中的关系拥有

请提前感谢!

编辑:我的问题是如何编写sql来实现这一目标。

2 个答案:

答案 0 :(得分:4)

一个选项是使用多重DELETE语句来删除所有三个表中的行,例如:

DELETE o.*
     , t.*
     , p.*
  FROM pet t
  JOIN own o
    ON o.petid = t.petid
  JOIN people p
    ON p.peopleid = o.peopleid
 WHERE p.peopleid = :b_peopleid

但是......外键存在问题。可以按照导致违反外键约束的顺序删除行。这对MyISAM来说不是问题,因为它不会强制执行外键。但是对于InnoDB,如果定义了外键约束,这可能是一个问题不幸的是,InnoDB不支持可延迟约束,因此最接近的解决方法是暂时禁用外键检查......

SET foreign_key_checks = 0 ;

然后是 DELETE 语句,然后重新启用外键检查......

SET foreign_key_checks = 1; 

但是这会禁用会话中的所有外键检查,而不仅仅是在DELETE中引用的表上定义的外键。因此,这种方法不太理想,因为可能会引入不一致的数据。

(例如,如果有另一个带有引用pet.petid的外键的表,我们从pet中删除&#34; parent&#34;行,这可能会在&#中留下一行34; child&#34;引用不存在的键的表。)

pet删除行?

数据模型表明pet可能与多个people相关。例如:

 
    pet:    petid    petname
            ------   -------
            1        Spot

    people: peopleid name
            -------- ------
            2        Jack
            3        Jill

    own:    petid    peopleid
            -------  --------
            1        2
            1        3

如果我们要删除&#34; Jack&#34;,我们可以删除&#34;拥有&#34;中的相关行。 (&#34;杰克&#34;和#34; Spot&#34;之间的关系。但在这种情况下,&#34; Spot&#34;也与#34; Jill&#34;有关。#&#34;。 39; own中引用&#34; Spot&#34;的另一行,因此我们无法移除&#34; Spot&#34;,而无需删除&#34; Spot& #34;&#34; Jill&#34;。

的关系

所以,问题是,我们真的想要删除&#34; Spot&#34;在这种情况下?

如果我们确实想要删除&#34; Spot&#34;,我们还需要从own删除该另一行,与#34; Spot&#34;和&#34;吉尔&#34;。我们可以使用两个own表的引用来实现这一点;一个得到&#34;杰克&#34;之间的关系和他拥有的pet,以及另一个所有引用&#34; Spot&#34;的own行。

DELETE r.*
     , t.*
     , p.*
  FROM pet t
  JOIN own r
    ON r.petid = t.petid
  JOIN own o
    ON o.petid = t.petid
  JOIN people p
    ON p.peopleid = o.peopleid
 WHERE p.peopleid = :b_peopleid

另一方面,如果我们不想删除&#34; Spot&#34;,因为&#34; Jill&#34; /&#34; Spot&#34; own中的行也引用&#34; Spot&#34;,我们可以做一些非常相似的事情。 (我不是一个SQL示例。)


处理可能适用于您的用例的外键关系的一些其他选项是BEFORE DELETE触发器和/或关于外键约束的ON DELETE规则。)

如果我们在引用ownpeople的{​​{1}}的外键上定义了ON DELETE CASCADE规则,我们可以允许从pet中删除行。

然后我们可以在我的答案中使用第一个示例DELETE语句,我们可以在DELETE列表中省略对own的引用,只需指定o.*t.*。 (我们仍然需要引用FROM子句中的p.*表,以获得own(&#34; Jack&#34;)和people之间的关系(&#34; Spot&#34;),因此我们知道要从pet删除哪些行。


否则,您可以运行三个单独的DELETE语句。但是执行DELETE语句的顺序实际上可能会删除您需要的信息,以确定需要删除其他表中的哪些行。这意味着您可能需要查询表以查找要删除的行,保存该信息,然后以适当的顺序执行所需的删除。


这种&#34;删除&#34;的另一种可行方法问题是通过更新&#34; deleted_flag&#34;来模拟删除。在行上键入列。

也就是说,应用程序不是发出DELETE语句,而是发出UPDATE以设置特殊用途&#34; deleted_flag&#34;在每一行。但是,必须为此设计应用程序用例,并且几乎所有查找&#34;未删除&#34;数据需要包含排除&#34;删除&#34;行。如果逻辑已删除的行确实需要从表中删除,则DELETE语句可以通过单独的批处理运行。

答案 1 :(得分:3)

我认为你需要的是ON DELETE CASCADE 使用此选项,如果删除主键行,则可以自动删除所有表引用。

在您的情况下,如果您使用peopleid删除某个人,则会自动删除Own表中的引用。

示例SQL语句

CREATE TABLE Own (
peopleid int(11) NOT NULL,
KEY peopleid (peopleid),
FOREIGN KEY (peopleid)
REFERENCES People (peopleid)
ON DELETE CASCADE
) ENGINE=InnoDB;  

由于pet表没有人员表的外键,因此您需要定义一个触发器,以便在删除人员条目时自动删除宠物条目。

CREATE TRIGGER pet_delete AFTER DELETE on own
FOR EACH ROW
BEGIN
    DELETE FROM Pet
    WHERE Pet.petid = old.petid;
END  

定义级联规则和触发器后,如果执行:

DELETE FROM People WHERE peopleid = 3  

它会自动从own表中删除peopleid = 3表和petid表中相应的Pet表。

查看此链接了解更多详情 http://www.mysqltutorial.org/mysql-on-delete-cascade/
MySQL Trigger: Delete From Table AFTER DELETE