我有三个表,其中一个是关系表,例如:
表人有主键: peopleid ;
表宠物有主键: petid ;
表拥有有两个外键: peopleid 和 petid ,它们一起作为表自己 <的主键/ p>
现在
我试图从表格中删除一个人 peopleid ,同时,应该删除此人拥有的宠物,以及存储在表格中的关系拥有
请提前感谢!
编辑:我的问题是如何编写sql来实现这一目标。
答案 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
规则。)
如果我们在引用own
和people
的{{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