Sql server 具有多个连接的复杂选择逻辑
我正在尝试处理我正在编写的查询中的逻辑 在使用删除之前,我想确保这是正确的 我想删除选择A中的所有行,其中A.xxxId存在于B中,B.YYYYD存在于C中,但C.YYYYD不存在于D中 这个查询有效吗Sql server 具有多个连接的复杂选择逻辑,sql-server,sql-server-2008,tsql,sql-server-2012,Sql Server,Sql Server 2008,Tsql,Sql Server 2012,我正在尝试处理我正在编写的查询中的逻辑 在使用删除之前,我想确保这是正确的 我想删除选择A中的所有行,其中A.xxxId存在于B中,B.YYYYD存在于C中,但C.YYYYD不存在于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.xxx
-- 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)
谢谢
这个查询有效吗?
对
但在这样做之前,请确保您创建了一个备份,以防出错
为备份准备表定义:
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);
只有你才能知道查询是否有效!在更新为DELETE之前,将查询作为SELECT运行是一个好主意。正如其他人指出的那样,备份也是确保您可以恢复任何意外删除的一种好方法 您也可以使用。我的示例使用以下示例数据: 样本数据 使用事务,您可以执行查询、捕获输出并回滚更改。此示例使用SQL Server创建的。这是一个临时表,除非存储结果,否则它们将丢失 范例 将回滚替换为提交将使您的更改成为数据库的永久部分 在实践中,我将这种方法与已经建议的其他方法相结合 编辑:在我的原始版本中,我使用了一个表变量,不知道这些变量不包括在事务中。请参阅优秀的SQL Server Central上的这篇文章,了解其原因
更新:重读我的答案后,我觉得我的开场白有点厚脸皮。我想说的是,非常糟糕的是,关注这里提供的技术比实际答案更重要 DELETE语句中的OUTPUT INTO子句最好是保存已删除的数据。因此,命令OUTPUT DELETED.*INTO将删除A中的行,并将这些删除的行插入临时备份表?在我看来,它将执行您所说的操作。
/* 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)
;
/* 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
;