SQL Server:使用一个表中的信息删除另一个表中的行
我在编写SQL Server脚本以从两个数据库中删除几行时遇到了一些困难。我已经看到了很多关于这个主题的其他问题,但是对于这个场景来说似乎没有什么是有效的。对于这样一个基本的问题,我提前表示歉意,但这是一个a不能搞砸的问题。我查询了很多数据,但很少对表进行写操作 我有两个表SQL Server:使用一个表中的信息删除另一个表中的行,sql,sql-server,Sql,Sql Server,我在编写SQL Server脚本以从两个数据库中删除几行时遇到了一些困难。我已经看到了很多关于这个主题的其他问题,但是对于这个场景来说似乎没有什么是有效的。对于这样一个基本的问题,我提前表示歉意,但这是一个a不能搞砸的问题。我查询了很多数据,但很少对表进行写操作 我有两个表rollinfo和defects,它们通过 defects.roll_id = rollinfo.roll_idx rollinfo表中有一列名为rollinfo.num\u defects 如果该值大于@MAX\u DEF
rollinfo
和defects
,它们通过
defects.roll_id = rollinfo.roll_idx
rollinfo
表中有一列名为rollinfo.num\u defects
如果该值大于@MAX\u 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
但是,我不确定是否可以通过将select语句更改为delete来同时删除两个表中的行,或者是否需要执行某种类型的“where exists”语句
为了记录在案,这将是大约20万行,所以如果有不止一种方法可以做到这一点,我想知道哪一种更有效
谢谢
丹,你试过这个吗
这可能有效,也可能无效,具体取决于您的数据库
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;
否则,在同一批中使用两次删除(您说要编写脚本,所以批处理是正确的做法)。在这种简单的情况下,您不需要事务,因为您已经知道您是唯一与DB交互的人:
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;
由于需要从两个表中删除,因此需要有两个
delete
语句,因此我认为最好的方法是将需要删除的ID写入一个临时表中,然后用它来驱动两个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
Use可以使用
级联删除
外键约束,因此您只需删除一次缺陷,它们将从相关表中删除。可能重复marc_s,这很有意义,我想我需要删除语句。我会尝试一下。我建议在事务中包装,以防在从ROLLINFO删除时删除第一个表后出现问题,否则,您可能无法重新创建id列表并重新运行删除。@EdwardComeau:Absolute-更新了我的响应,以突出显示您不能用一个delete
语句从两个表中删除的事实。不正确,这取决于数据库实现,有些oracle和mysql(innodb)版本支持它,这就是为什么我提出这两种解决方案,如果第一种方案不起作用(OP必须测试),那么第二种方案就出现了。好吧,问题被标记为[sql server],它肯定不支持这种语法。另一方面,我没有意识到其他数据库管理系统可能支持它。今天我学到了一些新东西。谢谢