2013-10-29 52 views
0

我目前在網站上使用PHP和SQL。有一個包含用戶(帳戶),組織和關係表的數據庫,用於將組織與帳戶相關聯(多對多關係)這是構建此SQL查詢的正確方法嗎?

當我從數據庫中刪除一個帳戶時,SQL查詢還應該刪除任何組織如果要刪除的帳戶是與組織關聯的唯一帳戶,則該帳戶已關聯。

我對SQL比較陌生,並且已經構建了一個查詢,該查詢應該在上述條件下從組織表中刪除組織。 這裏是我的查詢:

'DELETE FROM TBL_ORGANISATIONS WHERE id = (
    SELECT org_id FROM TBL_AFFILIATIONS WHERE account_email = :email AND (
     SELECT COUNT(*) FROM TBL_AFFILIATIONS WHERE org_id IN (
      SELECT org_id FROM TBL_AFFILIATIONS WHERE account_email = :email 
     ) 
    ) = 1 
)' 

這是正確的方式來構建這個查詢或者是有一個更清晰/更有效的方式來做到這一點?正如我前面提到的我是相當新的SQL,還沒有掌握所有的SQL關鍵字的概念,它可以在構造查詢,如下所示(JOIN等)

謝謝大家提前任何意見是有益的你可以提供。

順便說一句: 我使用PDO因此:電子郵件爲你想知道的那些。

回答

0

如果你有foreign key constraints,就像我認爲你應該那樣,那麼這個聲明將失敗,因爲聯盟記錄仍然指向要刪除的組織記錄。

您可以使用ON DELETE CASCADE刪除組織,就像Mihai在他的(現在刪除的)評論中建議的那樣,但要做到這一點,您仍然需要檢查是否只有一個聯繫人與組織相關聯。

在這種情況下,我寧願先查詢組織的ID。無論如何,您可能手頭都有,因爲您會知道您要刪除的帳戶的詳細信息。然後,先刪除帳戶,並在下刪除企業如果需要,用一個看起來像這樣的語句:

DELETE FROM TBL_ORGANISATIONS o 
WHERE 
    o.id = :ThatIdYouQueriedBefore AND 
    NOT EXISTS (SELECT 'x' FROM TBL_AFFILIATIONS a.org_id = o.id); 

個人我不級聯刪除一個大風扇,因爲看似很小的失誤可能會花費你很多數據,但即使你使用它們,我也不認爲這會讓這種特殊情況變得更容易。

+0

感謝您的回覆。我至今沒有使用外鍵,因爲我一直使用MyISAM作爲表引擎,但按照您的建議,我已將引擎更改爲InnoDB並添加了外鍵,因爲它們看起來像是在兩個表之間創建關係的正確方法。現在正在使用外鍵,這似乎是一個很好的解決方案。謝謝 –

0

我想我會做兩個邏輯查詢。如果您需要保證刪除總是一起發生,請在事務中自由換行,如果不刪除,則可以回滾。

第一,同時刪除該帳戶,該帳戶的組織隸屬關係使用單個查詢(在這裏我假設你的帳戶表名)

DELETE tbl_account,tbl_affiliations 
FROM tbl_account INNER JOIN tbl_affiliations 
    ON tbl_account.account_email = tbl_affiliations.account_email /* I am assuming join condition here, perhaps there is an id to be used instead */ 
WHERE tbl_account.acount_email = ? 

然後,刪除任何孤立的組織:

DELETE tbl_organizations 
FROM tbl_organizations LEFT JOIN tbl_affiliations 
    ON tbl_organizations.org_id = tbl_affiliations.org_id 
WHERE tbl_affiliations.org_id IS NULL 

請注意,由於上次查詢不依賴於任何特定於帳戶的信息,因此如果您不需要將組織刪除與帳戶同步發生,也可以考慮運行異步進程來清理孤立的組織刪除。

此方法的好處是,您可以始終使用第一個查詢以相同的方式刪除用戶帳戶,因爲無論是否有多個帳戶與組織關聯,這都可以工作。因此,您不需要任何額外的應用程序邏輯或SQL SELECT子查詢來查找單個帳戶與組織關聯的情況。

+0

感謝您的回覆。由於我現在使用外鍵約束,我認爲這可能不起作用,因爲組織表和附屬表之間的關係。但是,如果我沒有添加外鍵,這似乎是一個很好的解決方案,所以謝謝。 我會upvote你,但我不能,因爲我還沒有15聲望 –

+0

@BenGuest那麼,你真的不應該有一個外鍵約束之間的組織表和affiliations表與你使用它的方式。無論如何,我個人並不喜歡外鍵約束,因爲IMO應該在可能的情況下在應用層實現這種邏輯(從性能的角度來看是合理的)。這就是說,您可以在查詢期間關閉外鍵約束。 –

+0

林不知道我明白爲什麼它不是一個好主意,使用它們。擁有外鍵允許附屬關係表在賬戶電子郵件地址更改(這是賬戶表中的主鍵)時自動更新。我想我可以在PHP的一個單獨的查詢中做到這一點,但我可以讓數據庫引擎爲我處理。你的意思是說有外鍵可能會使查詢在更難以創建/更危險的數據庫中的其他數據(即更可能意外刪除其他數據)的問題中完成操作? –

0

由於您試圖一次刪除兩個表中的數據,因此您可以嘗試此操作。

DELETE from TBL_ORGANISATIONS TO JOIN TBL_AFFILIATIONS TA 
    ON(TO.id=TA.org_id) where TA.account_email=:email; 

在這裏,我們試圖使用TO(即ID)和foriegn關鍵TA(即org_id)的主鍵兩個表TBL_ORGANISATIONS和TBL_AFFILIATIONS刪除該行並添加條件使用where子句,其中TA.account_email =:電子郵件。

+0

嗯,我真的想從3個表中刪除數據:從帳戶表中刪除行,其中email = account_to_delete's_email,從affiliations表中刪除所有行,其中account_email = account_to_delete's_email,最後,從組織表中刪除行在附屬表中沒有任何參考 –