[英]How to Delete data in Both Tables in SQL Server?
我有一个表TableA,它的PK是AId。 我还有另一个表TableB,它的唯一列是BId。 BId实际上是AId的子集。 现在,我们不能使用FK(因为这个原因)。
如何在表A中删除表B中的TOP 1000行及其相关行(如果表A中存在相同的ID)?
一种解决方案是从表B中选择SELECT TOP 100)并保存到临时表,然后使用它删除表A中的数据,然后删除表B中的行。
但是它应该有一个更有效的方法来做到这一点。
我也尝试过:
DELETE TOP (1000) FROM tableA WHERE AId IN (SELECT BId FROM TableB)
但是,如何确定删除前1000个BId?
谢谢
一种方法是创建一个表变量,存储1000个ID并在两个删除操作中引用。 当然我不知道它们是否是整数,因此如果需要,请更改数据类型。 还有其他方法,我相信其他人会指出,但是如果我需要一致性,这是我的标准方法。
DECLARE @keyValues TABLE (keyValue INT);
INSERT INTO @keyValues
SELECT TOP 1000 FROM TABLEA WHERE AID IN (SELECT BID FROM TABLEB);
DELETE FROM TABLEB WHERE BID IN (SELECT keyValue FROM @keyValues);
DELETE FROM TABLEA WHERE AID IN (SELECT keyValue FROM @keyValues);
通常,一个DELETE
语句只能在一个表中更改数据。 因此,通常,您需要两个单独的DELETE
语句才能从两个表中删除行。
从技术上讲,您不必将BId
写入临时表,只需从TableB
读取两次即可。
SET TRANSACTION ISOLATION LEVEL SERIALIZABLE;
BEGIN TRANSACTION;
DELETE FROM TableA
WHERE TableA.AId IN
(
SELECT TOP(1000) TableB.BId
FROM TableB
ORDER BY TableB.BId
)
;
DELETE FROM TableB
WHERE TableB.BId IN
(
SELECT TOP(1000) TableB.BId
FROM TableB
ORDER BY TableB.BId
)
;
COMMIT TRANSACTION;
您需要确保两个查询中的1000 BId
集合相同,这意味着您必须将ORDER BY
与TOP
。 另外,您还应采取措施防止两个DELETE
语句之间的另一个进程对TableB
进行更改。
最后,处理并发问题(例如,通过将事务隔离级别设置为可序列化)可能会比将这1000个ID写入临时表产生更多的开销。
另一方面,您说“ BId实际上是AId的子集”。 因此, TableA
为TableA
, TableB
为细节。
从技术上讲,您可以使用ON DELETE CASCADE
选项定义外键。 从为什么不能使用外键约束这一问题对我来说还不清楚。
ALTER TABLE TableB WITH CHECK ADD CONSTRAINT [FK_TableB_TableA] FOREIGN KEY(BId)
REFERENCES TableA(AId) ON DELETE CASCADE
GO
ALTER TABLE TableB CHECK CONSTRAINT [FK_TableB_TableA]
GO
然后,您将仅从TableA
删除,而在TableB
子行将被外键约束删除。 很难说这是否比两个显式的DELETEs
更有效-您需要在硬件上进行测试。
在这种情况下,一个显式的DELETE
就足够了:
DELETE FROM TableA
WHERE TableA.AId IN
(
SELECT TOP(1000) TableB.BId
FROM TableB
ORDER BY TableB.BId
)
;
这也将解决并发问题。
其他可能的方式:
1)使用Output子句从TableB删除TOP(1000)(放入临时表),然后从TableA删除,其中该输出表中有AID。
要么
2)为TableB实现DELETE触发器,因此当从TableB中删除任何行时,它们也将自动从TableA中删除。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.