DELETE的现代替代......在哪里......不在(...)?

时间:2013-12-11 12:34:07

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

采用以下两个表变量,是否有任何(更快/更短/更有效)的替代方法可以删除@tbl_big@tbl_small内不存在的任何数据?原因是我有大量的数据选择,并且基于可选参数(在程序中)我在向用户呈现之前进一步过滤数据。

userId列在物理表中编入索引,这些表变量列是从中填充的。

DECLARE @tbl_big TABLE (userID int);
INSERT INTO @tbl_big (userID) VALUES (1),(5),(10),(20),(30),(40),(60),(100);

DECLARE @tbl_small TABLE (userID int);
INSERT INTO @tbl_small (userID) VALUES (1),(5),(10),(20)

-- this deletes 30,40,60,100 from @tbl_big
DELETE FROM 
    @tbl_big 
WHERE
    (userID NOT IN (SELECT userID FROM @tbl_small));

SELECT * from @tbl_big;

http://www.sqlfiddle.com/#!6/d41d8/12674

我确实想知道INTERSECTEXCEPT是否会这样做,但无法弄明白。

更新: EXCEPT / INTERSECT调查结果作为答案。我不确定从编码角度来看是否有更短的路径......?

4 个答案:

答案 0 :(得分:2)

通常,存在或左外连接都可以解决问题。

DELETE b FROM @tbl_big b
WHERE NOT EXISTS (
    SELECT 1 FROM @tbl_small s
    WHERE s.userID = b.userID);

OR

DELETE b FROM @tbl_big b
LEFT OUTER JOIN @tbl_small s
    ON s.userID = b.userID
WHERE s.userID IS NULL;

答案 1 :(得分:1)

这是现代的:)但我不确定它比不存在的删除更快:

DECLARE @tbl_big TABLE (userID int)
DECLARE @tbl_small TABLE (userID int)

INSERT INTO @tbl_big (userID) VALUES (1),(5),(10),(20),(30),(40),(60),(100)
INSERT INTO @tbl_small (userID) VALUES (1),(5),(10),(20)

;with deleting as (
SELECT * from @tbl_big
except
select * from @tbl_small)

DELETE b 
FROM 
    @tbl_big b
where exists ( 
select * from deleting c where c.userID = b.userID)

SELECT * from @tbl_big

答案 2 :(得分:1)

DECLARE @tbl_big TABLE (userID int)
DECLARE @tbl_small TABLE (userID int)
DECLARE @tbl_new TABLE (userID int)

INSERT INTO @tbl_big (userID) VALUES (1),(5),(10),(20),(30),(40),(60),(100)
INSERT INTO @tbl_small (userID) VALUES (1),(5),(10),(20)

INSERT INTO @tbl_new 
SELECT userID
FROM @tbl_big 
INTERSECT 
SELECT userID
FROM @tbl_small;

SELECT * from @tbl_new;

答案 3 :(得分:0)

我终于想出了EXCEPT,虽然它不容易阅读!

DELETE
    b
FROM 
    @tbl_big b INNER JOIN
    (
    SELECT
        *
    FROM
        @tbl_big EXCEPT 
    SELECT
        userID
    FROM
        @tbl_small) s ON s.userID = b.userID;

我现在也意识到INTERSECT实际上会删除错误的一半数据(例如数据NOT IN @tbl_small