具有多个JOINS的复杂选择逻辑

时间:2016-01-08 15:37:39

标签: sql-server sql-server-2008 tsql sql-server-2012

我试图在我写作的查询中完成逻辑。

我想确保在使用DELETE之前我有正确的。

我想删除(选择)A中所有行,其中a.xxxId存在于B中,而b.yyyId存在于C中,但其中c.yyyId不存在于D中。

此查询是否有效?

-- all a that are in b, 
-- that are in c,
-- that are NOT in d

-- change to DELETE

SELECT  a.*
FROM    A a
        JOIN    B b ON a.xxxId = b.xxxId
        JOIN    C c ON b.yyyId = c.yyyId
WHERE NOT EXISTS ( SELECT * FROM D d WHERE c.yyyId = d.yyyId)

谢谢!

2 个答案:

答案 0 :(得分:3)

  • 此查询会有效吗?

但在此之前,请确保在发生垃圾的情况下创建备份。

准备备份的表定义:

SELECT TOP (0) *
INTO TemporaryBackupTable
FROM a;

然后运行DELETE语句,它还会将已删除的记录插入准备好的备份表中。

DELETE a.*
OUTPUT DELETED.* INTO TemporaryBackupTable
FROM    A a
        JOIN    B b ON a.xxxId = b.xxxId
        JOIN    C c ON b.yyyId = c.yyyId
WHERE NOT EXISTS ( SELECT * FROM D d WHERE c.yyyId = d.yyyId);

答案 1 :(得分:2)

只有您可以判断查询是否有效!在更新到DELETE之前将查询作为SELECT运行是个好主意。正如其他人指出的那样,备份也是确保您可以恢复任何意外删除的好方法。

您也可以使用TRANSACTIONS。我的示例使用此示例数据:

示例数据

/* We'll use a temp table to test the transaction.
 */
CREATE TABLE #Sample    
    (
        Id    INT
    )
;

/* Populate sample values.
 */
INSERT INTO #Sample
    (
        Id
    )
VALUES
    (1),
    (2),
    (3),
    (4),
    (5)
;

使用TRANSACTION,您可以执行查询,捕获输出并回滚更改。此示例使用SQL Server创建的DELETED table。这是一个临时表,除非您存储结果,否则它们将丢失。

示例

/* Wrapping your statements in a transaction allows you to 
 * rollback the results.
 */
BEGIN TRANSACTION xy;

    /* The output clause allows you to inspect
     * the deleted records, using the deleted table.
     * This table is created by SQL Server for you.
     */
    DELETE
    FROM
        #Sample
    OUTPUT
        deleted.*
    WHERE
        Id > 3
    ;

ROLLBACK TRANSACTION xy;


    /* Outside the transaction the table still contains the 
     * original records.
     */
    SELECT
        *
    FROM
        #Sample
    ;

用COMMIT替换ROLLBACK将使您的更改成为数据库的永久部分。

在实践中,我将这种方法与已经建议的其他方法结合起来。

编辑:在我的原始版本中,我使用了一个表变量,不知道它们是否包含在事务中。有关原因,请参阅优秀的SQL Server Central上的blog

更新:重读我的回答后,我的开场白有点厚颜无耻。我试图做的非常重要的一点是,关注这里提供的技术比实际答案更重要。