这是构造此SQL查询的正确方法吗?

时间:2013-10-29 20:17:08

标签: php mysql sql

我目前正在网站上使用PHP和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因此:电子邮件让你们想知道。

3 个答案:

答案 0 :(得分: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);

就个人而言,我不是级联删除的忠实粉丝,因为看似小的错误可能会花费你很多数据,但即使你使用它们,我也不认为这使得这个特殊情况更容易。

答案 1 :(得分: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

请注意,由于最后一个查询不依赖于任何特定于帐户的信息,因此如果您不需要将组织删除与删除帐户同步发生,则还可以考虑运行异步过程来清理孤立的组织。 / p>

这种方法的好处是,您可以使用第一个查询以相同的方式删除用户帐户,因为无论是否有多个与组织关联的帐户,这都有效。因此,您不需要任何额外的应用程序逻辑或SQL SELECT子查询来查找与组织关联的单个帐户的情况。

答案 2 :(得分: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 =:email。