2014-09-13 246 views
0

我有三個表,其中之一是一個關係表,例如:SQL和外鍵約束刪除

人民有主鍵:的peopleid;
寵物有主鍵:petid;
自己有兩個外鍵:的peopleidpetid,他們一起作爲現在
我試圖刪除表的人一人給

自己的主鍵的peopleid,同時,寵物這個人自己應該刪除,以及關係存儲在表自己

請擺脫一些光線,提前致謝!

編輯:我的問題是如何編寫sql來實現這一點。

+0

對此有所瞭解?問題是什麼? – 2014-09-13 04:10:56

+0

@LarryLustig我試圖編寫sql來實現此目的.. – Arch1tect 2014-09-13 04:14:26

回答

1

我認爲你需要的是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; 

由於寵物表沒有外鍵百姓餐桌,你需要定義一個觸發自動刪除寵物的條目,當人們條目被刪除。

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 

它將從ownpeopleid = 3Pet表中相應petid自動刪除條目。

點擊此鏈接瞭解更多詳情。
http://www.mysqltutorial.org/mysql-on-delete-cascade/
MySQL Trigger: Delete From Table AFTER DELETE

+1

ON DELETE CASCADE規則將用於從'own'表中刪除相關行,當刪除'people'表中的行時,但不適用於'寵物'桌。 (因爲外鍵來自引用「pet」表的「自己」表)。 – spencer7593 2014-09-13 05:02:20

+0

是的你是對的。對於寵物桌,在他的回答中提到的一些觸發器需要被定義爲@ spencer7593 – cppcoder 2014-09-13 05:34:11

+0

,寵物可能由多個人擁有。在這種情況下,我不想刪除表Pet中的寵物....我應該如何修改觸發器來實現此目的? – Arch1tect 2014-09-13 07:03:37

1

一種選擇是使用多表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中刪除了「parent」行,這可能會在引用不存在的「child」表中留下一行鍵)。

pet刪除行(s)?

數據模型建議pet可能與多個people有關。例如:

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

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

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

如果我們要刪除「傑克」,我們可以在「自己」(以下簡稱「傑克」和「點」之間的關係刪除相關的行,但在這種情況下,「點」是。也與「Jill」有關,own中還有一行引用了「Spot」,所以我們不能刪除「Spot」,也沒有將「Spot」與「Jill」的關係刪除。 ,問題是,我們真的想在這種情況下刪除「Spot」嗎?

如果我們確實想刪除「Spot」,我們還需要從中刪除另一行3210也是關於「Spot」和「Jill」的那個。我們可以使用兩個引用own表;一個得到「Jack」和他自己擁有的pet之間的關係,另一個得到參照「Spot」的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 

在另一方面,如果我們不希望刪除「點」,因爲「吉爾」 /「點」在own行還引用了「點」,我們也許能夠非常做些什麼類似。 (我不是一個SQL例子這一點。)


一些其他的選擇來處理,可能是可行的爲您的使用情況是BEFORE DELETE觸發器外鍵關係,和/或外ON DELETE規則主要制約因素。)

如果我們對DELETE從own引用peoplepet的外鍵定義CASCADE規則,我們可以允許從own刪除行。

然後我們可以在我的答案中使用第一個示例DELETE語句,並且我們可以在DELETE列表中省略對o.*的引用,並且只指定t.*p.*。(我們仍然需要參考own表在FROM子句中,拿到之間people(「傑克」)和pet(「點」)的關係,所以我們知道要刪除的從pet行。


否則,您可以運行三個單獨的DELETE語句,但執行DELETE語句的順序可能實際上刪除了您需要的信息,以確定需要刪除其他表中的哪些行,這意味着您可能需要查詢表找到要刪除的行,保存該信息,然後按適當的順序執行所需的刪除操作。


這種「刪除」問題的另一種可行方法是模擬刪除,並在行上更新「deleted_flag」類型列。

也就是說,應用程序不是發出DELETE語句,而是發出UPDATE以在每一行上設置特殊用途「deleted_flag」。但是,必須爲此設計應用程序用例,幾乎所有查找「未刪除」數據的查詢都需要合併排除「已刪除」行的謂詞。如果邏輯上刪除的行實際上確實需要從表中刪除,那麼DELETE語句可以由單獨的批處理進程運行。