有人可以快速概述一下使用以下两个语句的利弊:
TRUNCATE TABLE dbo.MyTable
对比
DELETE FROM dbo.MyTable
似乎他们都在做同样的事情。但两者之间一定有区别。
有人可以快速概述一下使用以下两个语句的利弊:
TRUNCATE TABLE dbo.MyTable
对比
DELETE FROM dbo.MyTable
似乎他们都在做同样的事情。但两者之间一定有区别。
TRUNCATE
不会生成任何回滚数据,这使其闪电般快速。它只是释放表使用的数据页。
但是,如果您在事务中并希望能够“撤消”此删除,则需要使用DELETE FROM
,它提供了回滚的能力。
编辑: 请注意,以上对于 SQL Server 是不正确的(但它确实适用于 Oracle)。在 SQL Server 中,如果您在事务中并且该事务尚未提交,则可以回滚截断操作。从 SQL Server 的角度来看,DELETE FROM 和 TRUNCATE 之间的一个关键区别是:“DELETE 语句一次删除一行,并在事务日志中为每个删除的行记录一个条目。TRUNCATE TABLE 通过释放数据页来删除数据用于存储表数据并仅在事务日志中记录页面释放。”
换句话说,在 TRUNCATE 期间的日志记录较少,因为只有页面释放记录在事务日志中,而 DELETE FROM 记录了每行删除。这就是 TRUNCATE 快如闪电的原因之一。
另请注意,从该 MSDN 链接中,您不能截断由外键约束引用、参与索引视图或使用事务复制或合并复制发布的表。
编辑 2: 另一个关键点是 TRUNCATE TABLE 会将您的身份重置为初始种子,而 DELETE FROM 将从中断处继续递增。参考:本·罗宾逊的回答。
其他答案中未提及的另一个关键点是TRUNCATE TABLE
将您的身份重置为初始种子,而将从中断处继续递增。DELETE FROM
从安全角度来看,另一个区别是 TRUNCATE 需要对表有 ALTER 权限,而 DELETE 只需要对那个表有(鼓)DELETE 权限。
TRUNCATE TABLE
不记录交易。这意味着它对于大桌子来说是闪电般的快。缺点是您无法撤消操作。
DELETE FROM
在事务日志中记录正在删除的每一行,因此该操作需要一段时间并导致您的事务日志急剧增长。好处是您可以在需要时撤消操作。
SQL Server 中删除与截断的概述
在此连接后获取完整文章:SQL Server 中的删除与截断
/*Truncate - Syntax*/
TRUNCATE TABLE table_name
/*Delete - Syntax*/
DELETE FROM table_name
WHERE some_condition
我相信只有在显式事务中执行操作时才能回滚删除和截断。否则,您将不得不执行还原以恢复已删除的数据
根本区别在于它们的记录方式。DELETE 和 TRUNCATE 的记录方式不同,但两者都可以以完全相同的方式回滚。记录所有更改数据的操作。在 SQL Server 中,没有非日志操作之类的东西。
DELETE
vs之间的另一个区别TRUNCATE
是表损坏时的行为。
例如:
DELETE FROM table_name;
最终会出现错误:
消息 3314,第 21 级,状态 3,第 1 行
在撤消数据库“...”中记录的操作期间,日志记录 ID () 处发生错误。通常,特定故障以前会作为错误记录在 Windows 事件日志服务中。从备份中恢复数据库或文件,或修复数据库。
消息 0,级别 20,状态 0,行 0
当前命令发生严重错误。结果,如果有的话,应该丢弃。
虽然TRUNCATE
会工作:
TRUNCATE TABLE table_name;
-- Command(s) completed successfully.
非常重要的一件事(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
表上没有锁定,并且上面的查询也不会卡住。
加上所有的答案,另一点要考虑的是Truncate
不会触delete trigger
发表的,但delete
语句会delete trigger
为每一行触发表的。
truncate 不做任何记录,delete 做,所以如果你有很多记录,你的 trans log 是巨大的