如果不允许回滚TRUNCATE语句而不是在事务中回滚它的方式。请考虑以下代码并给予回复。
USE tempdb
GO
-- Create Test Table
CREATE TABLE TruncateTest (ID INT)
INSERT INTO TruncateTest (ID)
SELECT 1
UNION ALL
SELECT 2
UNION ALL
SELECT 3
GO
-- Check the data before truncate
SELECT * FROM TruncateTest
GO
-- Begin Transaction
BEGIN TRAN
-- Truncate Table
TRUNCATE TABLE TruncateTest
GO
-- Check the data after truncate
SELECT * FROM TruncateTest
GO
-- Rollback Transaction
ROLLBACK TRAN
GO
-- Check the data after Rollback
SELECT * FROM TruncateTest
GO
-- Clean up
DROP TABLE TruncateTest
GO
答案 0 :(得分:4)
Truncate Cannot Be Rolled Back Because It Is Not Logged是一种相当常见的SQL Server信念。但是,您问题中的代码只是验证了这实际上是一个神话。
与TRUNCATE
相比, DELETE
确实需要更少的 日志记录,因为它只会将页面解除引用和一些元数据更新记录到系统表中,而不是记录已删除行的全部内容到日志(See a detailed breakdown of logging here)。
SQL Server continues to lock解除分配的页面,直到事务提交阻止重新分配,因此ROLLBACK
的{{1}}只需要反转这些页面解除分配和系统表更新日志。
答案 1 :(得分:2)
无法回滚Truncate语句的概念通常被误解。
执行Truncate语句时,它不会记录在日志文件中,因为它是DDL语句。
因此,如果您截断表格,则无法回滚到截断之前的某个时间点。
但是,在事务中,允许回滚并且功能与其他任何回滚一样。
引用的回滚不是事务性回滚。
实质上:在发出COMMIT之前的任何地方,您都可以回滚TRUNCATE语句。在COMMIT之后,即使使用日志文件也无法回滚数据。不可恢复。
答案 2 :(得分:0)
在Oracle中,TRUNCATE语句在执行之前终止当前事务(我相信使用COMMIT)。然后,因为它被视为DDL语句,TRUNCATE执行时没有回滚的可能性。然后开始新的交易。
据我了解,Oracle中其他DDL语句的行为有点类似。
某些DBMS提供了事务性DDL语句 - 它也非常有用。