【发布时间】:2011-03-16 10:27:22
【问题描述】:
有人可以快速概述一下使用以下两种语句的优缺点吗:
TRUNCATE TABLE dbo.MyTable
对
DELETE FROM dbo.MyTable
说到底,他们似乎都在做同样的事情;但是两者之间一定有区别吗。
【问题讨论】:
标签: sql-server sql-server-2008 tsql sql-delete truncate
有人可以快速概述一下使用以下两种语句的优缺点吗:
TRUNCATE TABLE dbo.MyTable
对
DELETE FROM dbo.MyTable
说到底,他们似乎都在做同样的事情;但是两者之间一定有区别吗。
【问题讨论】:
标签: sql-server sql-server-2008 tsql sql-delete truncate
TRUNCATE 不会生成任何回滚数据,这使其速度快如闪电。它只是释放表使用的数据页。
但是,如果您在事务中并希望能够“撤消”此删除操作,则需要使用DELETE FROM,它提供了回滚功能。
编辑: 请注意,以上对于 SQL Server 是不正确的(但它确实适用于 Oracle)。在 SQL Server 中,如果您在事务中并且该事务尚未提交,则可以回滚截断操作。从 SQL Server 的角度来看,DELETE FROM 和 TRUNCATE 之间的一个关键区别是this: “DELETE 语句一次删除一行,并在事务日志中为每个删除的行记录一个条目。TRUNCATE TABLE 通过释放用于存储表数据的数据页来删除数据,并仅在事务日志中记录页面释放。 "
换句话说,TRUNCATE 期间的日志记录较少,因为事务日志中只记录页面释放,而 DELETE FROM 记录每行删除。这就是 TRUNCATE 快如闪电的原因之一。
还请注意,从该 MSDN 链接中,您不能截断由外键约束引用、参与索引视图或使用事务复制或合并复制发布的表。
编辑 2: 另一个关键点是 TRUNCATE TABLE 会将您的身份重置为初始种子,而 DELETE FROM 将从中断处继续递增。 参考:Ben Robinson 的回答。
【讨论】:
TRUNCATE 也可能会破坏一致性(=不检查外键,也不触发触发器)
其他答案中未提及的另一个关键点是TRUNCATE TABLE 将重置您的身份到初始种子,而DELETE FROM 将从哪里开始递增它停止了。
【讨论】:
从安全角度来看,另一个区别是 TRUNCATE 需要表的 ALTER 权限,而 DELETE 只需要(鼓)该表的 DELETE 权限。
【讨论】:
TRUNCATE TABLE 不记录事务。这意味着它对于大桌子来说是闪电般的快。缺点是无法撤消操作。
DELETE FROM 在事务日志中记录正在删除的每一行,因此该操作需要一段时间并导致您的事务日志急剧增长。好处是您可以根据需要撤消操作。
【讨论】:
SQL Server 中删除与截断的概述
在此连接后获取完整文章:Delete Vs Truncate in SQL Server
/*Truncate - Syntax*/
TRUNCATE TABLE table_name
/*Delete - Syntax*/
DELETE FROM table_name
WHERE some_condition
【讨论】:
我相信只有在显式事务中执行操作时才能回滚删除和截断。否则,您将不得不执行还原以恢复已删除的数据
【讨论】:
根本区别在于它们的记录方式。 DELETE 和 TRUNCATE 的记录方式不同,但都可以以完全相同的方式回滚。记录所有更改数据的操作。在 SQL Server 中,不存在非日志操作。
【讨论】:
有一点非常重要(imo)并且在其他答案中没有提到是TRUNCATE 需要架构稳定性锁Sch-S,而DELETE 使用行锁。让我们检查以下内容:
BEGIN TRANSACTION;
BEGIN TRY
-- Truncate below will take LCK_M_SCH_S lock for TABLE_A
TRUNCATE TABLE TABLE_A
-- Lets say the query below takes 5 hours to execute
INSERT INTO
TABLE_A
SELECT
*
FROM
GIANT_TABLE (NOLOCK)
END TRY
BEGIN CATCH
IF @@TRANCOUNT > 0
ROLLBACK TRANSACTION;
THROW
END CATCH
IF @@TRANCOUNT > 0
COMMIT TRANSACTION;
现在假设在此查询开始 1-2 分钟后,假设我们尝试执行以下操作:
SELECT COUNT(*) FROM TABLE_A (NOLOCK)
请注意,我使用了NOLOCK 子句。你认为现在会发生什么?此查询将等待 5 小时。为什么?因为NOLOCK 子句需要Sch-S 锁定TABLE_A,但TRUNCATE 子句已经有Sch-S。由于我们还没有提交事务,即使在 TRUNCATE 子句之后,锁仍然处于打开状态。表上的Sch-S 锁定基本上意味着TABLE_A 正在通过添加/删除列等进行更改,或者它正在被截断。您甚至无法执行以下操作:
SELECT object_id('TABLE_A')
这也会卡住 5 个小时。但是,如果您将 TRUNCATE 替换为 DELETE FROM,您将看到表上将没有 Sch-S 锁定,并且上述查询不会卡住。
【讨论】:
DELETE 与 TRUNCATE 之间的另一个区别是表损坏时的行为。
例如:
DELETE FROM table_name;
会报错:
消息 3314,第 21 级,状态 3,第 1 行
在撤消数据库“...”中记录的操作期间,日志记录 ID () 处发生错误。通常,特定故障以前会作为错误记录在 Windows 事件日志服务中。从备份中恢复数据库或文件,或修复数据库。
消息 0,级别 20,状态 0,行 0
当前命令发生严重错误。结果(如果有)应丢弃。
虽然TRUNCATE 可以工作:
TRUNCATE TABLE table_name;
-- Command(s) completed successfully.
【讨论】:
加上所有的答案,还有一点要考虑Truncate不会触发表的delete trigger,但是delete语句会为每一行触发表的delete trigger。
【讨论】:
truncate 不做任何记录,delete 做,所以如果你有很多记录,你的 trans log 是巨大的
【讨论】: