【发布时间】:2011-01-08 17:53:41
【问题描述】:
SQL Server 中是否有批量删除的解决方案?
我不能使用 TRUNCATE,因为我想使用 WHERE 来限制行数。
有没有像批量复制(bcp)这样的删除数据?
【问题讨论】:
标签: sql sql-server tsql sql-server-2008
SQL Server 中是否有批量删除的解决方案?
我不能使用 TRUNCATE,因为我想使用 WHERE 来限制行数。
有没有像批量复制(bcp)这样的删除数据?
【问题讨论】:
标签: sql sql-server tsql sql-server-2008
您可以使用循环逐块删除:
这是我每次删除 100 条记录的解决方案:
DECLARE @Rows INT
SET @Rows = 1
WHILE (@Rows > 0)
BEGIN
with ToDelete(EMailNotificationID)
as
(
select top 100 q.EMailNotificationID from email
)
delete from ToDelete
SET @Rows = @@ROWCOUNT
END
【讨论】:
【讨论】:
在处理数百万行时,我更喜欢使用 WHERE 语句并使用 SELECT INTO 复制表,删除原始表并重命名副本(恢复为原始名称)。
不过,您应该牢记 (FK) 键、约束等内容。但是使用这种方法可以避免日志的badazz-size,并且可以避免大量删除块的时间消耗。
/斯内德克
【讨论】:
刚刚在处理临时表时遇到了类似的问题,该表在使用适当的锁进行扩展时遇到了问题。
由于我们只在一个位置引用了相关表,因此我们只是用动态表名的查询替换了该引用,动态表名是使用类似于 gbn 建议的“选择进入”创建的。
这是可维护的,因为临时表仅在代码中的一个位置引用,并且在仓库上下文中,额外的数据库调用以及表创建的费用是合理的。如果您只有几百条记录或在代码中多次引用该表,那么这种方法可能行不通。
【讨论】:
没有。
您想要一个带有 WHERE 子句的 DELETE:这是标准 SQL。
你可以像这样批量删除:
SELECT 'Starting' --sets @@ROWCOUNT
WHILE @@ROWCOUNT <> 0
DELETE TOP (xxx) MyTable WHERE ...
或者如果你想删除很高比例的行...
SELECT col1, col2, ... INTO #Holdingtable
FROM MyTable WHERE ..opposite condition..
TRUNCATE TABLE MyTable
INSERT MyTable (col1, col2, ...)
SELECT col1, col2, ... FROM #Holdingtable
【讨论】:
BULK_LOGGED 或SIMPLE 并使用WITH TABLOCK 锁定表以进行第二次INSERT,否则事务日志仍然会很大。见social.technet.microsoft.com/wiki/contents/articles/…
如果您想删除表的一部分而不是TRUNCATE,您可以做几件事。
你可以选择表格的一部分到一个新表格中,然后将两者切换,如下所示:
SELECT *
INTO tmp_MyTable
FROM MyTable
WHERE Key='Value'
IF @@ROWCOUNT > 0
BEGIN
EXEC sp_rename MyTable, old_MyTable, NULL
EXEC sp_rename tmp_MyTable, MyTable, NULL
TRUNCATE old_MyTable
END
其次,如果您使用分区,您可以在相同的分区方案上创建一个相同的(空)表。如果该表是根据您的归档/清除逻辑分区的,您可以从您的主表到新表然后截断新表。例如:
ALTER TABLE MyTable
SWITCH PARTITION 15 TO purge_MyTable PARTITION 2
GO;
TRUNCATE TABLE purge_MyTable
附言。 SQL 2005/08 Ent 中提供了分区。
希望这会有所帮助!
【讨论】:
DBCC SHRINKFILE。
Sychare Jedko,
TRUNCATE 的优点是避免在日志文件中记录每一次删除。 TRUNCATE 语句将为整个批次创建一个条目(在日志中)。
【讨论】: