2013-10-29 54 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,最后,从组织表中删除行在附属表中没有任何参考 –