SQL中TRUNCATE和DELETE的区别是什么?

如果你的答案是针对特定平台的,请注明。


当前回答

“Truncate不会记录任何东西”是正确的。我想更进一步:

Truncate不会在事务的上下文中执行。

截断比删除的速度优势应该是明显的。根据你的情况,这种优势从微不足道到巨大不等。

然而,我看到截断无意中破坏了引用完整性,并违反了其他约束。通过在事务外部修改数据而获得的权力,必须与在没有安全网的情况下走钢丝时继承的责任相平衡。

其他回答

下面是一些不同之处。我强调了特定于oracle的特性,希望社区也能添加其他供应商的特定差异。对于大多数供应商来说常见的差异可以直接放在标题下面,并在下面突出显示差异。

总体概述

如果您想要快速删除表中的所有行,并且您确实确定要这样做,并且表上没有外键,那么TRUNCATE可能会比delete更快。

必须考虑各种特定于系统的问题,详情如下。

语句类型

删除是DML,截断是DDL(什么是DDL和DML?)

提交和回滚

供应商变量

SQL *服务器

Truncate可以回滚。

PostgreSQL

Truncate可以回滚。

甲骨文

因为TRUNCATE是DDL,它涉及两次提交,一次在语句执行之前,一次在语句执行之后。因此,Truncate不能回滚,截断过程中的失败无论如何都会发出提交。

然而,请看下面的闪回。

空间回收

Delete不能恢复空间,Truncate只能恢复空间

甲骨文

如果使用了REUSE STORAGE子句,那么数据段就不会被重新分配,如果要用数据重新加载表,这样做的效率会稍微高一些。重置高水位标志。

行范围

Delete可用于删除所有行或仅删除行的子集。Truncate删除所有行。

甲骨文

在对表进行分区时,可以隔离地截断各个分区,从而可以部分删除表的所有数据。

对象类型

Delete可以应用于集群内的表和表。Truncate仅适用于表或整个集群。(可能是Oracle特有的)

数据对象标识

甲骨文

Delete不会影响数据对象id,但truncate会分配一个新的数据对象id,除非自该表创建以来从未对该表进行过插入操作。即使是一个回滚的插入操作也会导致在截断时分配一个新的数据对象id。

闪回(Oracle)

闪回可以跨删除操作,但截断操作可以防止闪回操作之前的状态。

然而,从11gR2 FLASHBACK ARCHIVE功能允许这一点,除了在快速版

在Oracle中使用FLASHBACK http://docs.oracle.com/cd/E11882_01/appdev.112/e41502/adfns_flashback.htm#ADFNS638

特权

变量

甲骨文

可以将一个表上的Delete授权给另一个用户或角色,但是截断不能不使用DROP ANY table授权。

Redo /。

删除会产生少量的重做和大量的撤销。Truncate生成的两者数量都可以忽略不计。

索引

甲骨文

截断操作使不可用的索引重新可用。删除则不然。

外键

当启用的外键引用表时,不能应用截断。使用delete的处理取决于外键的配置。

表锁

甲骨文

Truncate需要一个排他表锁,delete需要一个共享表锁。因此,禁用表锁是防止对表进行截断操作的一种方法。

触发器

DML触发器不会在截断时触发。

甲骨文

DDL触发器是可用的。

远程执行

甲骨文

不能在数据库链接上发出Truncate命令。

标识列

SQL *服务器

Truncate重置IDENTITY列类型的序列,delete则不会。

结果集

在大多数实现中,DELETE语句可以向客户端返回已删除的行。

例如,在Oracle PL/SQL子程序中,你可以:

DELETE FROM employees_temp
WHERE       employee_id = 299 
RETURNING   first_name,
            last_name
INTO        emp_first_name,
            emp_last_name;

TRUNCATE是快的,DELETE是慢的。

尽管TRUNCATE没有问责制。

DELETE The DELETE command is used to remove rows from a table. A WHERE clause can be used to only remove some rows. If no WHERE condition is specified, all rows will be removed. After performing a DELETE operation you need to COMMIT or ROLLBACK the transaction to make the change permanent or to undo it. Note that this operation will cause all DELETE triggers on the table to fire. TRUNCATE TRUNCATE removes all rows from a table. The operation cannot be rolled back and no triggers will be fired. As such, TRUCATE is faster and doesn't use as much undo space as a DELETE. DROP The DROP command removes a table from the database. All the tables' rows, indexes and privileges will also be removed. No DML triggers will be fired. The operation cannot be rolled back. DROP and TRUNCATE are DDL commands, whereas DELETE is a DML command. Therefore DELETE operations can be rolled back (undone), while DROP and TRUNCATE operations cannot be rolled back.

来自:http://www.orafaq.com/faq/difference_between_truncate_delete_and_drop_commands

对于SQL Server或MySQL,如果有一个带有自动递增的PK, truncate将重置计数器。

下面是这些sql命令之间一些重要区别的总结:

SQL truncate命令:

1)它是一个DDL(数据定义语言)命令,因此诸如COMMIT和ROLLBACK之类的命令不适用于此命令(这里的例外是PostgreSQL和MSSQL,它们的TRUNCATE命令的实现允许该命令在事务中使用)

2)你不能撤销删除记录的操作,它是自动发生的,并且是不可逆的(除了上面的例外情况-但是,如果该操作包含在TRANSACTION块中并且会话没有关闭)。Oracle -包含两个隐式提交,一个在语句执行之前,一个在语句执行之后。因此,该命令不能被撤回,而运行时错误将导致提交

3)删除表中的所有记录,记录不能被限制删除。对于Oracle,当表被划分为每个分区时,单个分区可以被隔离截断(TRUNCATE),从而可以从表中部分删除所有数据

4)释放表中数据所占用的空间(在磁盘的表空间中)。对于Oracle -如果你使用REUSE STORAGE子句,数据段将不会回滚,也就是说,你将保留已删除行的空间分配给表,如果表要用数据重新加载,这可能会更有效一点。高分将被重置

5) TRUNCATE比DELETE工作得快得多

6)在TRUNCATE的情况下,Oracle闪回防止回到术前状态

7) Oracle - TRUNCATE不能授予(GRANT)不使用DROP ANY表

8) TRUNCATE操作使不可用的索引重新可用

9)当启用的外键指向另一个表时,TRUNCATE不能使用,那么你可以:

执行命令:DROP CONSTRAINT,然后TRUNCATE,然后通过CREATE CONSTRAINT或播放它 SET FOREIGN_KEY_CHECKS = 0;然后截断,然后:SET_FOREIGN_KEY_CHECKS = 1;

10) TRUNCATE需要一个排他表锁,因此,关闭排他表锁是防止在表上进行TRUNCATE操作的一种方法

11) DML触发器在执行TRUNCATE后不会触发(所以在这种情况下要非常小心,如果在表中定义了删除触发器来执行自动的表清理或行删除后的登录操作,则不应该使用TRUNCATE)。在Oracle上,DDL触发器被触发

12) Oracle - TRUNCATE不能用于:database link的情况 13) TRUNCATE不返回删除的记录数量

14)事务日志-一个指示页面释放的日志(删除数据,释放用于存储表数据的数据页的分配,并只将页面释放写入事务日志)-执行速度比DELETE更快。TRUNCATE只需要调整数据库中指向表(High Water Mark)的指针,数据立即被删除,因此它使用更少的系统资源和事务日志

15)性能(获得锁)-表和页锁-在执行过程中不会降低性能

16) TRUNCATE不能用于涉及事务复制或合并复制的表

SQL删除命令:

1)该命令为DML (Data Manipulation Language)命令,因此使用了COMMIT和ROLLBACK命令

2)可以使用ROLLBACK命令撤销删除记录的操作

3)从表中删除全部或部分记录,您可以使用WHERE子句限制要删除的记录

4)不释放表中数据占用的空间(在表空间中-在磁盘上)

5) DELETE比TRUNCATE慢得多

6) Oracle Flashback适用于DELETE

7) Oracle -对于DELETE,您可以使用GRANT命令

8) DELETE操作不会使不可用的索引重新可用

9)如果外键enabled是指另一个表,可以(或不)应用,取决于外键配置(如果没有),请:

执行命令:DROP CONSTRAINT,然后TRUNCATE,然后通过CREATE CONSTRAINT或播放它 SET FOREIGN_KEY_CHECKS = 0;然后截断,然后:SET_FOREIGN_KEY_CHECKS = 1;

10) DELETE需要一个共享表锁

11)引发火灾

12) DELETE可用于:database link的情况

13) DELETE返回已删除记录的数量

14)事务日志-对于每个删除的记录(每次删除一行,并为每个删除的行在事务日志中记录一个条目)-执行速度比TRUNCATE慢。执行DELETE语句后,表可能仍然包含空白页。DELETE需要读取记录、检查约束、更新块、更新索引以及生成重做/撤销。所有这些都需要时间,因此它所花费的时间比TRUNCATE要长得多

15)性能(获得锁)-记录锁-在执行过程中降低性能-表中的每条记录都被锁定以便删除

16)可以在事务性复制或合并复制的表上使用DELETE