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

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


当前回答

下面是一些不同之处。我强调了特定于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不会记录任何东西”是正确的。我想更进一步:

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

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

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

如果不小心使用Delete/Truncate从表中删除了所有数据。您可以回滚已提交的事务。恢复上次备份并运行事务日志,直到将要执行删除/截断操作。

以下相关信息来自一篇博客文章:

While working on database, we are using Delete and Truncate without knowing the differences between them. In this article we will discuss the difference between Delete and Truncate in Sql. Delete: Delete is a DML command. Delete statement is executed using a row lock,each row in the table is locked for deletion. We can specify filters in where clause. It deletes specified data if where condition exists. Delete activities a trigger because the operation are logged individually. Slower than Truncate because it Keeps logs Truncate Truncate is a DDL command. Truncate table always lock the table and page but not each row.As it removes all the data. Cannot use Where condition. It Removes all the data. Truncate table cannot activate a trigger because the operation does not log individual row deletions. Faster in performance wise, because it doesn't keep any logs. Note: Delete and Truncate both can be rolled back when used with Transaction. If Transaction is done, means committed then we can not rollback Truncate command, but we can still rollback Delete command from Log files, as delete write records them in Log file in case it is needed to rollback in future from log files. If you have a Foreign key constraint referring to the table you are trying to truncate, this won't work even if the referring table has no data in it. This is because the foreign key checking is done with DDL rather than DML. This can be got around by temporarily disabling the foreign key constraint(s) to the table. Delete table is a logged operation. So the deletion of each row gets logged in the transaction log, which makes it slow. Truncate table also deletes all the rows in a table, but it won't log the deletion of each row instead it logs the deallocation of the data pages of the table, which makes it faster. ~ If accidentally you removed all the data from table using Delete/Truncate. You can rollback committed transaction. Restore the last backup and run transaction log till the time when Delete/Truncate is about to happen.

对原始答案的一个小修正——删除也会产生大量的重做(因为undo本身是由重做保护的)。这可以从autotrace输出中看到:

SQL> delete from t1;

10918 rows deleted.

Elapsed: 00:00:00.58

Execution Plan
----------------------------------------------------------
   0      DELETE STATEMENT Optimizer=FIRST_ROWS (Cost=43 Card=1)
   1    0   DELETE OF 'T1'
   2    1     TABLE ACCESS (FULL) OF 'T1' (TABLE) (Cost=43 Card=1)




Statistics
----------------------------------------------------------
         30  recursive calls
      12118  db block gets
        213  consistent gets
        142  physical reads
    3975328  redo size
        441  bytes sent via SQL*Net to client
        537  bytes received via SQL*Net from client
          4  SQL*Net roundtrips to/from client
          2  sorts (memory)
          0  sorts (disk)
      10918  rows processed

下面是我对SQL Server中DELETE和TRUNCATE的区别的详细回答

•删除数据:首先,两者都可以用于从表中删除行。 但是,根据提供程序的功能,DELETE不仅可以用于从表中删除行,还可以用于从VIEW或OPENROWSET或OPENQUERY的结果中删除行。

•FROM子句:使用DELETE,您还可以使用另一个FROM子句根据另一个表的行从一个表/视图/rowset_function_limited中删除行。在那个FROM子句中,您还可以编写正常的JOIN条件。实际上,通过将SELECT替换为DELETE并删除列名,可以从不包含任何聚合函数的SELECT语句创建DELETE语句。 对于TRUNCATE,你不能这样做。

•WHERE: TRUNCATE不能有WHERE条件,但DELETE可以。这意味着使用TRUNCATE您不能删除特定的行或特定的行组。 TRUNCATE TABLE类似于不带WHERE子句的DELETE语句。

•性能:TRUNCATE TABLE更快,使用更少的系统和事务日志资源。 其中一个原因是两个语句都使用了锁。DELETE语句使用行锁执行,表中的每一行都被锁定以便删除。TRUNCATE TABLE总是锁定表和页,而不是每一行。

•事务日志:DELETE语句一次删除一行,并在事务日志中为每行创建单独的条目。 TRUNCATE TABLE通过释放用于存储表数据的数据页来删除数据,并且在事务日志中只记录页的释放。

•page:执行DELETE语句后,表中仍然可以包含空页。 TRUNCATE通过释放用于存储表数据的数据页来删除数据。

•Trigger: TRUNCATE不会激活表上的删除触发器。因此,在使用TRUNCATE时必须非常小心。如果在表上定义了delete Trigger以在删除行时执行一些自动清理或记录操作,则永远不应该使用TRUNCATE。

•标识列:如果表包含标识列,则使用TRUNCATE,该列的计数器将重置为为该列定义的种子值。如果没有定义种子,则使用默认值1。 DELETE不会重置标识计数器。因此,如果希望保留标识计数器,请使用DELETE。

•Replication: DELETE可以用于事务性复制或合并复制中使用的表。 而TRUNCATE不能用于事务性复制或合并复制中涉及的表。

•Rollback: DELETE语句可以回滚。 TRUNCATE也可以回滚,前提是它被包含在TRANSACTION块中并且会话没有关闭。一旦会话关闭,您将无法回滚TRUNCATE。

• Restrictions : The DELETE statement may fail if it violates a trigger or tries to remove a row referenced by data in another table with a FOREIGN KEY constraint. If the DELETE removes multiple rows, and any one of the removed rows violates a trigger or constraint, the statement is canceled, an error is returned, and no rows are removed. And if DELETE is used against View, that View must be an Updatable view. TRUNCATE cannot be used against the table used in Indexed view. TRUNCATE cannot be used against the table referenced by a FOREIGN KEY constraint, unless a table that has a foreign key that references itself.

最大的区别是truncate是不记录日志的操作,而delete是。

简单地说,这意味着在数据库崩溃的情况下,不能通过截断恢复所操作的数据,但可以通过删除恢复。

详情请点击这里