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

为了回答DROP和TRUNCATE之间的区别问题,我写了一个关于这个问题的答案,但是我认为这是一个耻辱,不要分享,所以我会发表我自己的答案,我自己的问题…是甚至道德? 🙂

编辑:如果你的答案是平台特定的,你可以指出。

这是一个差异列表。 我已经突出了Oracle特有的function,希望社区也可以添加其他供应商的具体差异。 大多数供应商常见的差异可以直接在标题下方,下面突出显示差异。


总体概述

如果你想快速删除一个表中的所有行,而且你确实想要这样做,而且你没有对表的外键,那么TRUNCATE可能会比DELETE 。

必须考虑各种系统特定的问题,如下所述。


语句types

删除是DML,截断是DDL


提交和回滚

由供应商variables

SQL *服务器

截断可以回滚。

PostgreSQL的

截断可以回滚。

神谕

由于TRUNCATE是DDL,它涉及两个提交,一个在语句执行之前和一个之后。 Truncate因此不能被回滚,并且截断进程中的失败将会发出一个提交。

但是,请参阅下面的闪回。


空间开垦

删除不恢复空间,截断恢复空间

神谕

如果使用REUSE STORAGE子句,那么数据段不会被解除分配,如果要重新载入数据,这可能会更有效率。 高水位重置。


行范围

删除只能删除一些行。 截断删除所有行。

神谕

对表进行分区时,可以将各个分区单独截断,因此可以部分删除所有表中的数据。


对象types

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


数据对象身份

神谕

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


闪回(Oracle)

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

但是从11gR2开始,FLASHBACK ARCHIVEfunction允许使用此function,Express Edition除外

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


特权

variables

神谕

删除可以授予一个表到另一个用户或angular色,但截断不能没有使用DROP ANY TABLE授予。


重做/撤消

删除会生成less量的重做和大量的撤消操作。 截断产生每个可以忽略不计的量。


索引

神谕

截断操作会使不可用的索引再次可用。 删除不。


外键

当启用的外键引用表时,不能应用截断。 删除的处理取决于外键的configuration。


表locking

神谕

截断需要独占表锁,删除需要共享表锁。 因此,禁用表锁是防止对表进行截断操作的一种方法。


触发器

DML触发器不会触发截断。

神谕

DDL触发器可用。


远程执行

神谕

截断不能通过数据库链接发出。


标识列

SQL *服务器

截断重置IDENTITY列types的序列,删除不。


结果集

在大多数实现中, 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 | +----------------------------------------+----------------------------------------------+ | 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) | +----------------------------------------+----------------------------------------------+ 

所有的好的答案,我必须补充:

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

下降

DROP命令从数据库中删除一个表。 所有表的行,索引和特权也将被删除。 没有DML触发器将被解雇。 操作无法回滚。

截短

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

删除

DELETE命令用于从表中删除行。 WHERE子句可以用来只删除一些行。 如果未指定WHERE条件,则将删除所有行。 执行DELETE操作后,您需要COMMIT或ROLLBACK事务以使更改永久或撤消。 请注意,此操作将导致表中的所有DELETE触发器触发。

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

使用SQL Server或MySQL,如果有自动增量的PK,truncate会重置计数器。

“截断不logging任何东西”是正确的。 我会更进一步:

截断不在事务的上下文中执行。

truncate over delete的速度优势应该是显而易见的。 这种优势从微不足道到巨大,取决于你的情况。

但是,我已经看到截断无意间破坏了参照完整性,并且违反了其他限制。 通过修改交易以外的数据获得的权力必须与您在没有networking的情况下走钢丝时所承担的责任相平衡。

删除VS摘要在SQL服务器中截断
对于完整的文章请按照此链接: http : //dotnetmob.com/sql-server-article/delete-vs-truncate-in-sql-server/

在这里输入图像说明

取自dotnet mob文章: 在SQL Server中删除Vs Truncate

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

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

TRUNCATE只需调整表格(高水位标记)的数据库中的指针,然后poof! 数据不见了

这是Oracle特有的AFAIK。

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

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

在处理数据库时,我们使用Delete和Truncate而不知道它们之间的差异。 在本文中,我们将讨论Sql中的Delete和Truncate之间的区别。

删除:

  • 删除是一个DML命令。
  • 删除语句是使用行锁执行的,表中的每一行都被locking删除。
  • 我们可以在where子句中指定filter。
  • 如果条件存在,则删除指定的数据。
  • 由于操作是单独logging的,因此删除触发器的活动。
  • 比截断慢,因为它保持日志

截短

  • 截断是一个DDL命令。
  • 截断表总是locking表和页面,但不是每一行,因为它删除所有的数据。
  • 不能使用Where条件。
  • 它删除所有的数据。
  • 截断表无法激活触发器,因为该操作不logging单个行删除。
  • 在性能上更快,因为它不保留任何日志。

注意:与Transaction一起使用时,Delete和Truncate都可以回退。 如果事务完成,意味着提交,那么我们不能回滚Truncate命令,但是我们仍然可以从日志文件中回滚删除命令,因为删除写入将它们logging在日志文件中,以防以后需要从日志文件中回滚。

如果您有一个外键约束引用了正在尝试截断的表,那么即使引用表中没有数据,这也不起作用。 这是因为外键检查是使用DDL而不是DML完成的。 这可以通过临时禁用对表的外键约束来解决。

删除表是一个logging操作。 所以删除每行logging在事务日志中,这使得缓慢。 截断表也会删除表中的所有行,但不会logging每行的删除,而是logging表的数据页的取消分配,这使得它更快。

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

TRUNCATE是DDL语句,而DELETE是DML语句。 以下是两者之间的差异:

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

  2. TRUNCATE始终删除表中的所有行,并将表保留为空,并且表结构保持不变,而如果使用where子句, DELETE可能会有条件地删除。

  3. TRUNCATE TABLE语句删除的行无法恢复,您无法在TRUNCATE语句中指定where子句。

  4. TRUNCATE语句不会触发与DELETE语句上的删除触发器相反的触发器

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

截短

  • 它比DELETE使用更less的系统和事务日志资源。
  • 通过释放用于存储表格数据的数据页面来删除数据,并且只有页面释放被logging在事务日志中。
  • 删除表中的所有行,但是表结构,列,约束,索引等仍然存在。 新行的标识使用的计数器重置为列的种子。
  • 您不能在由FOREIGN KEY约束引用的TRUNCATE TABLE上使用TRUNCATE TABLE 。 由于TRUNCATE TABLE未logging,因此无法激活触发器。
  • 不能回滚。
  • 这是DDL命令。
  • 重置表的身份

删除

  • 一次删除一行,并在每个删除行的事务日志中logging一个条目。
  • 如果要保留身份计数器,请改用DELETE 。 如果要删除表定义及其数据,请使用DROP TABLE语句。
  • 可以使用或不使用WHERE子句
  • 激活触发器。
  • 可以回滚。
  • 这是DML命令。
  • 不会重置表的身份。

注意:如果当前会话未closures,则在由TRANSACTION包围时, DELETETRUNCATE都可以回滚。 如果TRUNCATE写入TRANSACTION包围的查询编辑器中,并且会话closures,则不能回滚,但可以回滚DELETE

在SQL Server 2005中,我相信你可以回滚一个截断

删除

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

对原来的答案进行小的修改 – 删除也会产生大量的重做(因为撤销本身是通过重做来保护的)。 这可以从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 

如果包装在一个事务中,TRUNCATE可以回滚。

请参阅下面的两个参考文献并testing自己: –

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

TRUNCATE与DELETE是SQL访谈中臭名昭着的问题之一。 只要确保你向访问者正确解释,或者可能会让你付出代价。 问题是没有多less人知道,所以如果你告诉他们Yes Truncate可以回滚,他们很可能会认为答案是错误的。

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/

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

这里是我详细的答案在SQL Server中的DELETE和TRUNCATE之间的区别

删除数据 :首先,两者都可以用来删除表中的行。
但是,DELETE可以用来除去表中的行,也可以从VIEW或者OPENROWSET或OPENQUERY的结果中去除提供者的function。

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

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

性能 :TRUNCATE TABLE速度更快,并使用更less的系统和事务日志资源。 其中一个原因是两个语句使用的锁。 DELETE语句是使用行锁执行的,表中的每一行都被locking以便删除。 TRUNCATE TABLE总是locking表格和页面,但不locking每一行。

事务日志 :DELETE语句一次删除一行,并在每个行的事务日志中创build单个条目。
TRUNCATE TABLE通过释放用于存储表数据的数据页来删除数据,并仅在事务日志中logging页解除分配。

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

触发器 :TRUNCATE不激活表上的删除触发器。 所以在使用TRUNCATE时一定要小心。 如果在表中定义删除触发器时删除行,则不应使用TRUNCATE来执行自动清理或logging操作。

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

复制 :DELETE可用于事务复制或合并复制中使用的表。
虽然TRUNCATE不能用于涉及事务复制或合并复制的表。

回滚 :DELETE语句可以回滚。
TRUNCATE也可以回滚,只要它被包含在一个TRANSACTION块中并且会话没有closures。 一旦会话closures,您将无法回滚TRUNCATE。

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

简而言之,truncate不会logging任何东西(所以速度要快得多,但不能被撤销),而logging删除(可以是更大事务的一部分,将会回滚等)。 如果在dev中的表中有不需要的数据,通常最好是截断,因为不会冒充填事务日志的风险

最大的区别是截断是非logging操作,而删除是。

简单的说,就是说在发生数据库崩溃的情况下,不能通过truncate来恢复操作的数据,但是可以删除。

更多细节在这里

这很方便的一个重要原因是当你需要刷新数百万行表中的数据,但不想重build它。 “删除*”将永远占用,而截断的性能影响可以忽略不计。

无法通过dblink执行DDL。

我会在matthieu的post上发表评论,但我还没有代表呢…

在MySQL中,自动递增计数器被截断重置,但不被删除。

截断不是在SQL Server中logging任何东西。 truncate不会logging任何信息,但会logging您为其发射TRUNCATE的表的数据页的取消分配。

如果我们在开始定义事务,截断的logging可以回滚,我们可以在回滚之后恢复截断的logging。 但是在提交截断事务之后,不能从事务日志备份中恢复被截断的logging。

截断也可以回滚在这里exapmle

 begin Tran delete from Employee select * from Employee Rollback select * from Employee 

SQL中的截断和删除是用于从表中删除或删除数据的两个命令。 尽pipe在本质上相当基本,但是在使用它之前熟悉细节之前,Sql命令可能会产生很多麻烦。 如果需要删除太多的数据,并且日志段不够,可能导致命令select不正确的过程可能非常缓慢,甚至可能会导致日志段丢失。 这就是为什么知道何时使用截断和删除命令在SQL中至关重要,但在使用这些命令之前,您应该了解截断和删除之间的区别,并根据它们,我们应该能够找出何时删除是更好的选项数据或TRUNCATE应该用来清除表。

请参阅点击这里

通过发出TRUNCATE TABLE语句,指示SQL Server删除表中的每个logging,而不进行任何logging或事务处理。

删除

当DELETE语句执行时没有WHERE子句,它将删除所有的行。 但是,插入新logging时,标识值会从11(最大标识)增加到12,不会重置,而会继续增加。 截短

当TRUNCATE语句被执行时,它将删除所有的行。 但是,插入新logging时,标识值将从11(原始值)增加。 TRUNCATE将标识值重置为表格的原始种子值。

下降

与TRANSACTION一起使用时,DELETE和TRUNCATE都可以回滚。

如果事务完成,意味着COMMITED,那么我们不能回滚TRUNCATE命令,但是我们仍然可以从LOG文件中回滚DELETE命令,因为DELETE将它们logging在日志文件中,以防将来从LOG文件中回滚。