Reputation: 7092
I'm trying to work through the logic in a query I'm writing.
I wanted to make sure I have this correct before I use a DELETE.
I want to delete(select) all rows in A where a.xxxId exists in B and b.yyyId exists in C but where c.yyyId does NOT exist in D.
Would this query work?
-- 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)
Thanks!
Upvotes: 2
Views: 91
Reputation: 5030
Only you can tell if the query works! Running the query as a SELECT before updating to a DELETE is a good idea. As others have pointed out taking a backup is also a great way of ensuring you can restore any accidental deletions.
You can also use TRANSACTIONS. My example uses this sample data:
Sample Data
/* 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)
;
Using a TRANSACTION you can execute your query, capture the output and rollback the changes. This example uses the DELETED table created by SQL Server. This is a temporary table, unless you store the results they will be lost.
Example
/* 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
;
Replacing ROLLBACK with COMMIT will make your changes a permanent part of the database.
In practice I'd combined this approach with the others already suggested.
EDIT: In my original version I used a table variable, not knowing these are not included in transactions. See this blog on the excellent SQL Server Central for why this is.
UPDATE: Having reread my answer it strikes me that my opening sentence is a bit cheeky. The point I was trying to make, very badly, is it's more important to focus on the techniques provided here than the actual answer.
Upvotes: 2
Reputation: 14077
But before doing that, make sure you create a backup in case crap happens.
Prepare a table definition for a backup:
SELECT TOP (0) *
INTO TemporaryBackupTable
FROM a;
And then run DELETE statement, which also will insert deleted records into prepared backup table.
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);
Upvotes: 3