我试图在我写作的查询中完成逻辑。
我想确保在使用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)
谢谢!
答案 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。
更新:重读我的回答后,我的开场白有点厚颜无耻。我试图做的非常重要的一点是,关注这里提供的技术比实际答案更重要。