SQL Server:使用一个表中的信息删除另一个表中的行

时间:2016-10-10 18:04:53

标签: sql sql-server

我在编写一些SQL Server脚本以从两个数据库中删除几行时遇到一些困难。我已经看到了很多关于这个主题的其他问题,但似乎没有什么对这个场景有用。我提前为这样一个基本问题道歉,但这是一个不能搞砸的问题。我查询了很多数据,但我很少写表格。

我有两个表defectsdefects.roll_id = rollinfo.roll_idx ,它们由

链接
rollinfo

rollinfo.num_defects表中有一列名为@MAX_DEFECTS

如果该值大于defects,我想删除它。另外,我想从SELECT D.ROLL_ID, R.ROLL_IDX FROM VISION17SLITTER.DBO.ROLLINFO R INNER JOIN VISION17SLITTER.DBO.DEFECTS D ON D.ROLL_ID = R.ROLL_IDX WHERE R.NUM_DEFECTS > @MAX_DEFECTS 表中删除任何相应的行。

选择此信息很简单:

{{1}}

但是我不确定是否可以通过将select语句更改为删除来一次从两个表中删除行,或者我是否需要执行某些类型的"其中存在"言。

对于记录,这将是大约200k行,所以如果有多种方法可以做到这一点,我想知道哪个更有效。

谢谢,

2 个答案:

答案 0 :(得分:3)

由于您需要从两个表中删除,因此您需要有两个DELETE语句,因此我认为最好的方法就是写下这些ID&#39}需要删除到临时表中,然后使用它来驱动两个DELETE语句:

-- create the temp table - you didn't mention what the datatype for these two columns is - adapt as needed
CREATE TABLE #IDsToBeDeleted (ID INT NOT NULL)  

-- select those ID's you want to delete into the temp table
INSERT INTO #IDsToBeDeleted (ID)  
    SELECT
        D.ROLL_ID
    FROM 
        VISION17SLITTER.DBO.ROLLINFO R
    INNER JOIN 
        VISION17SLITTER.DBO.DEFECTS D ON D.ROLL_ID = R.ROLL_IDX
    WHERE
        R.NUM_DEFECTS > @MAX_DEFECTS

-- based on the temp table, now delete from the two tables  
-- again, from your question it isn't entirely clear which 
-- is the "parent" table, and which the "child" table - so you
-- might need to change the order of deleting those rows to
-- match your situation

BEGIN TRANSACTION
BEGIN TRY    
    DELETE FROM VISION17SLITTER.DBO.DEFECTS 
    WHERE ROLL_ID IN (SELECT ID FROM #IDsToBeDeleted)    

    DELETE FROM VISION17SLITTER.DBO.ROLLINFO 
    WHERE ROLL_IDX IN (SELECT ID FROM #IDsToBeDeleted)

    COMMIT TRANSACTION
END TRY
BEGIN CATCH
    -- report and log the error
    ROLLBACK TRANSACTION
END CATCH

答案 1 :(得分:0)

你试过这个吗?

根据您的数据库,这可能有效,也可能无效。

DELETE D, R
FROM
    VISION17SLITTER.DBO.ROLLINFO R
    INNER JOIN
    VISION17SLITTER.DBO.DEFECTS D
    ON D.ROLL_ID = R.ROLL_IDX
WHERE R.NUM_DEFECTS > @MAX_DEFECTS;

否则,在同一批次中使用两个删除(您说要编写脚本,因此批处理是正确的)。在这种简单的情况下,您不需要交易,因为您已经知道您是唯一与数据库交互的人:

DELETE D
FROM
    VISION17SLITTER.DBO.ROLLINFO R
    INNER JOIN
    VISION17SLITTER.DBO.DEFECTS D
    ON D.ROLL_ID = R.ROLL_IDX
WHERE R.NUM_DEFECTS > @MAX_DEFECTS;

DELETE R
FROM
    VISION17SLITTER.DBO.ROLLINFO R
WHERE R.NUM_DEFECTS > @MAX_DEFECTS;

GO

如果您真的不希望在应用程序静止时手动启动脚本,则必须考虑并发性并且实际事务处于有序状态:

BEGIN TRANSACTION

  DELETE D
  FROM
    VISION17SLITTER.DBO.ROLLINFO R
    INNER JOIN
    VISION17SLITTER.DBO.DEFECTS D
    ON D.ROLL_ID = R.ROLL_IDX
  WHERE R.NUM_DEFECTS > @MAX_DEFECTS;

  DELETE R
  FROM
    VISION17SLITTER.DBO.ROLLINFO R
  WHERE R.NUM_DEFECTS > @MAX_DEFECTS;

COMMIT;