SQL中TRUNCATE和DELETE的区别是什么

SQL中的TRUNCATEDELETE有什么区别?

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

569781 次浏览

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

<人力资源>

总体概述

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

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

<人力资源>

语句类型

Delete是DML, Truncate是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功能允许这一点,除了在快速版

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

<人力资源>

特权

变量

甲骨文

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

<人力资源>

重做/撤销

删除会产生少量的重做和大量的撤销。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;

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

简而言之,truncate不会记录任何内容(因此更快,但不能撤消),而delete会记录日志(并且可以是更大事务的一部分,将回滚等)。如果您在开发中有不想在表中使用的数据,通常最好截断,因为您不会冒填满事务日志的风险

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

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

更多细节在这里

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

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

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

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

它方便的一个重要原因是,当您需要刷新数百万行表中的数据,但又不想重新构建它时。“Delete *”会花费很长时间,而Truncate对性能的影响可以忽略不计。

都是很好的答案,我必须补充一句:

因为TRUNCATE TABLE是一个DDL (数据定义语言),而不是一个DML (数据操作语言)命令,所以Delete Triggers不会运行。

一眨眼的功夫就不能做DDL。

我想对matthieu的帖子发表评论,但我还没有得到代表…

在MySQL中,自动递增计数器通过truncate重置,而不是通过delete重置。

TRUNCATE是快的,DELETE是慢的。

尽管TRUNCATE没有问责制。

是的,DELETE比较慢,TRUNCATE比较快。为什么?

DELETE必须读取记录,检查约束,更新块,更新索引,并生成重做/撤销。所有这些都需要时间。

TRUNCATE只是在数据库中为表(High Water Mark)调整一个指针,然后!数据不见了。

这是Oracle特有的,AFAIK。

对原始答案的一个小修正——删除也会产生大量的重做(因为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 2005我相信你可以回滚截断

TRUNCATE是DDL语句,而DELETE是DML语句。以下是两者的区别:

  1. 由于TRUNCATE是一个DDL (数据定义语言)语句,因此不需要提交来使更改永久生效。这就是为什么被truncate删除的行不能回滚的原因。另一方面,DELETE是一个DML (数据操作语言)语句,因此需要显式提交以使其效果永久。

  2. TRUNCATE总是从表中删除所有行,使表为空,表结构完整,而DELETE如果使用where子句,则可以有条件地删除。

  3. TRUNCATE TABLE语句删除的行不能被恢复,并且不能在TRUNCATE语句中指定where子句。

  4. TRUNCATE语句不会触发触发器,相反,DELETE语句会触发delete触发器

在这里是与主题相关的非常好的链接。

truncate和delete的区别如下:

+----------------------------------------+----------------------------------------------+
|                Truncate                |                    Delete                    |
+----------------------------------------+----------------------------------------------+
| We can't Rollback after performing     | We can Rollback after delete.                |
| Truncate.                              |                                              |
|                                        |                                              |
| Example:                               | Example:                                     |
| BEGIN TRAN                             | BEGIN TRAN                                   |
| TRUNCATE TABLE tranTest                | DELETE FROM tranTest                         |
| SELECT * FROM tranTest                 | SELECT * FROM tranTest                       |
| ROLLBACK                               | ROLLBACK                                     |
| SELECT * FROM tranTest                 | SELECT * FROM tranTest                       |
+----------------------------------------+----------------------------------------------+
| Truncate reset identity of table.      | Delete does not reset identity of table.     |
+----------------------------------------+----------------------------------------------+
| It locks the entire table.             | It locks the table row.                      |
+----------------------------------------+----------------------------------------------+
| Its DDL(Data Definition Language)      | Its DML(Data Manipulation Language)          |
| command.                               | command.                                     |
+----------------------------------------+----------------------------------------------+
| We can't use WHERE clause with it.     | We can use WHERE to filter data to delete.   |
+----------------------------------------+----------------------------------------------+
| Trigger is not fired while truncate.   | Trigger is fired.                            |
+----------------------------------------+----------------------------------------------+
| Syntax :                               | Syntax :                                     |
| 1) TRUNCATE TABLE table_name           | 1) DELETE FROM table_name                    |
|                                        | 2) DELETE FROM table_name WHERE              |
|                                        |    example_column_id IN (1,2,3)              |
+----------------------------------------+----------------------------------------------+

DELETE语句:该命令只根据where子句中给定的条件从表中删除行,如果没有指定条件,则从表中删除所有行。但是它不会释放包含表的空间。

SQL DELETE语句的语法是:

DELETE FROM table_name [WHERE condition];

TRUNCATE语句:该命令用于删除表中的所有行,并释放包含表的空间。

删除

DELETE is a DML command
DELETE you can rollback
Delete = Only Delete- so it can be rolled back
In DELETE you can write conditions using WHERE clause
Syntax – Delete from [Table] where [Condition]

截断

TRUNCATE is a DDL command
You can't rollback in TRUNCATE, TRUNCATE removes the record permanently
Truncate = Delete+Commit -so we can't roll back
You can't use conditions(WHERE clause) in TRUNCATE
Syntax – Truncate table [Table]

详情请浏览

http://www.zilckh.com/what-is-the-difference-between-truncate-and-delete/

并不是说截断不记录SQL Server中的任何内容。truncate不记录任何信息,但它记录您触发truncate的表的数据页的释放。

如果在开始时定义事务,则可以回滚被截断的记录,回滚后可以恢复被截断的记录。但不能在提交截断事务后从事务日志备份中恢复截断记录。

在这个例子中,Truncate也可以被rollback

begin Tran
delete from  Employee


select * from Employee
Rollback
select * from Employee

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

下面的相关信息来自一篇博文:

当工作在数据库,我们使用删除和截断没有 知道它们之间的区别。在本文中,我们将讨论 Sql中Delete和Truncate的区别

删除:

  • Delete是一个DML命令。
  • Delete语句使用行锁执行,表中的每一行都被锁定以便删除。
  • 我们可以在where子句中指定过滤器。
  • 如果条件存在,则删除指定的数据。
  • 删除触发器的活动,因为操作是单独记录的。
  • 比Truncate慢,因为它保存日志

截断

  • Truncate是一个DDL命令。
  • 截断表总是锁定表和页,而不是每一行。因为它删除了所有的数据。
  • 不能使用Where条件。
  • 它删除所有的数据。
  • 截断表无法激活触发器,因为该操作不会记录单个行删除。
  • 在性能方面更快,因为它不保存任何日志。

注:Delete和Truncate在使用时都可以回滚 事务。如果事务完成,意味着提交,那么我们不能 rollback Truncate命令,但仍然可以rollback Delete命令 从日志文件,因为删除写入记录在日志文件,以防它是

.

.

如果你有一个外键约束指向表 尝试截断,这将不会工作,即使引用表没有 数据在里面。这是因为外键检查是用DDL完成的 而不是DML。可以通过暂时禁用

.

.

删除表是一个日志操作。所以每一行的删除得到 记录在事务日志中,这使得它很慢。截断表 还删除表中的所有行,但不会记录删除 对象的数据页的释放记录为每一行

~如果你不小心从表中删除了所有的数据使用 删除/截断。您可以回滚已提交的事务。恢复 最后一次备份并运行事务日志,直到删除/截断

如果将TRUNCATE包装在事务中,则可以回滚。

请参阅下面的两个参考资料并自行测试:-

http://blog.sqlauthority.com/2007/12/26/sql-server-truncate-cant-be-rolled-back-using-log-files-after-transaction-session-is-closed/

http://sqlblog.com/blogs/kalen_delaney/archive/2010/10/12/tsql-tuesday-11-rolling-back-truncate-table.aspx

截断与删除是SQL面试中最臭名昭著的问题之一。一定要向面试官解释清楚,否则可能会让你丢掉这份工作。问题是没有多少人意识到这一点,所以如果你告诉他们YES Truncate可以回滚,他们很可能会认为答案是错误的。

SQL中的Truncate和Delete是两个命令,用于从表中删除或删除数据。虽然这两个Sql命令在本质上都很基本,但在使用它之前,除非你熟悉细节,否则会造成很多麻烦。 一个不正确的命令选择可能导致非常缓慢的进程,甚至可以爆炸的日志段,如果需要删除太多的数据和日志段是不够的。这就是为什么知道什么时候在SQL中使用truncate和delete命令是至关重要的,但在使用这些命令之前,你应该意识到truncate和delete之间的区别,并根据它们,我们应该能够找出delete何时是删除数据的更好选择,而truncate何时应该用于清除表

参考检查点击这里

通过发出TRUNCATE TABLE语句,您将指示SQL Server删除表中的每条记录,而不进行任何日志记录或事务处理。

这两个操作的另一个区别是,如果表包含一个标识列,则在TRUNCATE下该列的计数器将重置1(或为该列定义的种子值)。DELETE没有这种影响。

删除

DELETE命令用于删除表中的行。WHERE子句只能用于删除某些行。如果没有指定WHERE条件,将删除所有行。在执行DELETE操作之后,您需要COMMIT或ROLLBACK事务以使更改永久生效或撤销它。注意,该操作将触发表上的所有DELETE触发器。

截断

TRUNCATE删除表中的所有行。操作不能回滚,也不会触发任何触发器。因此,TRUCATE速度更快,并且不像DELETE那样使用那么多的撤消空间。

下降

DROP命令从数据库中删除一个表。所有表的行、索引和特权也将被删除。不会触发DML触发器。该操作不能回退。


DROP和TRUNCATE是DDL命令,而DELETE是DML命令。因此,DELETE操作可以回滚(取消),而DROP和TRUNCATE操作不能回滚。

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

下降

DROP命令从数据库中删除一个表。所有表的行、索引和特权也将被删除。不会触发DML触发器。该操作不能回退。

截断

TRUNCATE删除表中的所有行。操作不能回滚,也不会触发任何触发器。因此,TRUNCATE更快,并且不像DELETE那样使用那么多的撤消空间。截断时将添加表级锁。

删除

DELETE命令用于删除表中的行。WHERE子句只能用于删除某些行。如果没有指定WHERE条件,将删除所有行。在执行DELETE操作之后,您需要COMMIT或ROLLBACK事务以使更改永久生效或撤销它。注意,该操作将触发表上的所有DELETE触发器。删除时将添加行级锁。

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

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

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

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

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

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

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

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

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

标识列:如果表包含标识列,则使用TRUNCATE将该列的计数器重置为为该列定义的种子值。如果没有定义种子,则使用默认值1。 DELETE不会重置标识计数器。所以如果你想保留标识计数器,使用DELETE代替

复制: DELETE可用于事务性复制或合并复制中使用的表 而TRUNCATE不能用于事务性复制或合并复制中涉及的表。< / p >

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

限制:如果DELETE语句违反触发器或试图删除由另一个表中的数据引用的行,则该语句可能会失败。如果DELETE删除了多行,并且任何被删除的行违反了触发器或约束,则该语句将被取消,返回错误,并且不删除任何行 如果对视图使用DELETE,则该视图必须是可更新视图。 TRUNCATE不能用于索引视图中使用的表 TRUNCATE不能用于由FOREIGN KEY约束引用的表,除非表具有引用自身的外键

在SQL server中删除和截断的摘要
完整文章请按此链接:http://codaffection.com/sql-server-article/delete-vs-truncate-in-sql-server/

enter image description here

摘自dotnet mob文章:删除Vs截断SQL Server

DELETE语句可以有一个WHERE子句来删除特定的记录,而TRUNCATE语句不需要任何子句并擦除整个表。 重要的是,DELETE语句记录删除日期,而TRUNCATE语句不记录删除日期

针对microsoft sql server的另一个不同之处在于,对于delete,你可以使用output语句来跟踪哪些记录已被删除,例如:

delete from [SomeTable]
output deleted.Id, deleted.Name

你不能用truncate这样做。

截断命令用于重新初始化表,这是一个DDL命令,删除表中的所有行。删除是一个DML命令,用于根据某些条件删除一行或一组行,如果没有指定condition,则该命令将从表中删除所有行。

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

SQL truncate命令:

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

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

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

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

5) TRUNCATE比DELETE工作得快得多

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

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(数据操纵语言)命令,因此以下命令用于此命令:COMMIT和ROLLBACK

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

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

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

5) DELETE比TRUNCATE工作得慢得多

6) Oracle Flashback适用于DELETE

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

8) DELETE操作不会使不可用的索引再次可用

9) DELETE如果外键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可用于事务性复制或合并复制中的表