ChatGPT解决这个技术问题 Extra ChatGPT

SQL中的TRUNCATE和DELETE有什么区别

SQL 中的 TRUNCATEDELETE 有什么区别?

如果您的答案是特定于平台的,请指出。

所有答案都是特定于平台的。标准 SQL 中没有 TRUNCATE 命令。因此,它是一项专有功能,对每个 DBMS 供应商来说意味着不同的东西。
答案是非常具体的实现,因为它必须是,因为正如 sqlvogel 指出的那样,这是一个非标准命令(TRUNCATE)。要么将此标记为“oracle”,要么让它成为一个社区维基风格的答案,并为每个主要的 RDBMS(Oracle、MS-MSQL、PostgreSQL 都实现 TRUNCATE ......)
如果 Transaction 已经完成,意味着 COMMITED,那么我们不能回滚 TRUNCATE 命令,但是我们仍然可以从 LOG 文件中回滚 DELETE 命令,因为 DELETE 写入会将它们记录在 Log 文件中,以防将来需要从 LOG 文件中回滚。

1
14 revs, 4 users 99%

这是差异列表。我已经强调了 Oracle 特定的特性,希望社区也可以添加其他供应商的特定差异。大多数供应商共有的差异可以直接放在标题下方,下面突出显示差异。

总体概述

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

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

报表类型

删除是 DML,截断是 DDL (What is DDL and DML?)

提交和回滚

因供应商而异

SQL*服务器

截断可以回滚。

PostgreSQL

截断可以回滚。

甲骨文

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

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

空间回收

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

甲骨文

如果您使用 REUSE STORAGE 子句,则不会取消分配数据段,如果要重新加载表中的数据,这可能会稍微更有效。高水位线被重置。

行范围

删除可用于删除所有行或仅删除部分行。截断删除所有行。

甲骨文

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

对象类型

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

数据对象身份

甲骨文

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

闪回(甲骨文)

闪回适用于删除,但截断可防止闪回到操作之前的状态。

但是,从 11gR2 开始,FLASHBACK ARCHIVE 功能允许这样做,但在 Express Edition 中除外

Use of FLASHBACK in Oracle http://docs.oracle.com/cd/E11882_01/appdev.112/e41502/adfns_flashback.htm#ADFNS638

特权

多变的

甲骨文

可以将表上的删除权限授予另一个用户或角色,但如果不使用 DROP ANY TABLE 权限,则不能截断。

重做/撤消

删除会产生少量的重做和大量的撤消。 Truncate 生成的每一个都可以忽略不计。

索引

甲骨文

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

外键

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

表锁定

甲骨文

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

触发器

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

甲骨文

DDL 触发器可用。

远程执行

甲骨文

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

身份列

SQL*服务器

截断重置 IDENTITY 列类型的序列,删除不会。

结果集

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

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

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

不明白你的第四条语句:如果我说 DELETE [] FROM Table;然后 * 该表中的所有行都将被删除,除非 FK 停止它。顺便说一句,我猜这是特定于 SQL Server 的,您不能在带有 FK 的表上使用 TRUNCATE。
更多评论:我不同意您的第三条陈述,除非它是特定于 Oracle 的。至少对于 SQL S。如果您删除或截断,除非您特别要求,否则您不会恢复空间(即数据库文件不会在硬盘驱动器上缩小)。
第 5 条语句:您可以在 sql 2008 r2 上回滚 TRUNCATE TABLE
Postgresql 可以回滚 TRUNCATE,因此也不会自动提交它。
DELETE 返回删除的行数,但 TRUNCATE 不返回。这是非常愚蠢的一点,但值得一提:)
N
Naresh Ravlani

截断和删除的区别如下:

+----------------------------------------+----------------------------------------------+
|                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 reset identity of table 是什么意思?但是,删除呢?
@jWeaver:这意味着当您将主键字段的 Identity Specification 属性设置为 True 时,因此当您将数据插入该表时,主键列的值类似于 1,2,3,4,5....(如果 Identity 开始从 1 开始,种子为 1),当您截断表时,它将丢失所有标识值,因此当您再次开始将数据插入该表时,它将从 1 开始,而不是最后离开的位置。在 DELETE 中,它是相反的,即使在您执行 DELETE 语句之后它也会保留标识值。抱歉,上图中的 DELETE 列中的第二个比较点错误。
好像您正在回答 SQL SERVER
TRUNCATE 和 DELETE 都可以在 SQL SERVER 中回滚。并且在第二行 DELETE 不会重置身份。现在你怎么能编辑这篇文章?这就是在 StackOverflow 中使用图片的坏处。
截断正在回滚! (SQL 服务器)
C
Community

DROP DROP 命令从数据库中删除一个表。所有表的行、索引和权限也将被删除。不会触发任何 DML 触发器。该操作无法回滚。 TRUNCATE TRUNCATE 从表中删除所有行。该操作无法回滚,也不会触发任何触发器。因此,TRUNCATE 速度更快,并且不像 DELETE 那样使用太多的撤消空间。截断时将添加表级锁。 DELETE DELETE 命令用于从表中删除行。 WHERE 子句可用于仅删除某些行。如果未指定 WHERE 条件,则将删除所有行。执行 DELETE 操作后,您需要 COMMIT 或 ROLLBACK 事务以使更改永久化或撤消它。请注意,此操作将触发表上的所有 DELETE 触发器。删除时会添加行级锁。

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


D
David Ferenczy Rogožan

所有好的答案,我必须添加:

由于 TRUNCATE TABLE 是 DDL (Data Defination Language),而不是 DML (Data Manipulation Langauge) 命令,因此 Delete Triggers 不会运行。


啊,触发器......这是一个很好的观点。如果可以的话,我会把它添加到我制作的列表中,并感谢 Polara。
SQL Server 不允许您使用外键截断表,因此您的级联点可能没有实际意义,具体取决于平台。
PostgreSQL 有一个“TRUNCATE 触发器”
S
Shamseer K

SQL 服务器中删除与截断的摘要
完整文章请点击此链接:http://codaffection.com/sql-server-article/delete-vs-truncate-in-sql-server/

https://i.stack.imgur.com/Bil4e.jpg

摘自 dotnet mob 文章:Delete Vs Truncate in SQL Server


D
David Ferenczy Rogožan

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


澄清一下,如果表有一个定义为 IDENTITY 的列,这适用于 SQL Server。 Delete 会保留最后一个自动分配的 ID,而 Truncate 会重置计数器。
由于问题被标记为 ORACLE,因此这个答案是错误的,因此被否决。
糟糕,没有看到 oracle 标记 :)
+1 true,并将其重置为 0。如果您希望它改为 1DBCC CHECKIDENT (table_name, RESEED, 1)
我已将此添加到社区答案中,并使其对记录特定于供应商的问题更加友好
W
Walter Mitty

“截断不记录任何内容”是正确的。我会更进一步:

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

truncate 相对于 delete 的速度优势应该是显而易见的。根据您的情况,这种优势从微不足道到巨大。

但是,我看到 truncate 无意中破坏了参照完整性,并违反了其他约束。您通过在事务之外修改数据获得的权力必须与您在没有网络的情况下走钢丝时继承的责任相平衡。


D
David Ferenczy Rogožan

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

由于 TRUNCATE 是 DDL(数据定义语言)语句,因此不需要提交即可使更改永久化。这就是为什么 truncate 删除的行无法回滚的原因。另一方面,DELETE 是一个 DML(数据操作语言)语句,因此需要显式提交才能使其效果永久化。 TRUNCATE 总是从表中删除所有行,使表为空且表结构完整,而如果使用 where 子句,则 DELETE 可能有条件地删除。 TRUNCATE TABLE 语句删除的行无法恢复,不能在 TRUNCATE 语句中指定 where 子句。 TRUNCATE 语句不会触发触发器,而不是在 DELETE 语句上的删除触发器

Here 是与主题相关的非常好的链接。


D
DCookie

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

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

TRUNCATE 只是为表(高水位线)调整数据库中的指针,然后噗!数据不见了。

这是 Oracle 特定的,AFAIK。


PostgreSQL 也与此类似。
w
wpzone4u

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

以下相关信息来自a blog post

在处理数据库时,我们在不知道它们之间的差异的情况下使用 Delete 和 Truncate。在本文中,我们将讨论 Sql 中 Delete 和 Truncate 的区别。删除:删除是一个 DML 命令。删除语句使用行锁执行,表中的每一行都被锁定以进行删除。我们可以在 where 子句中指定过滤器。如果 where 条件存在,它将删除指定的数据。删除活动是一个触发器,因为该操作是单独记录的。比 Truncate 慢,因为它保留日志 Truncate Truncate 是一个 DDL 命令。截断表总是锁定表和页面,但不是每一行。因为它删除了所有数据。不能使用 Where 条件。它删除所有数据。截断表无法激活触发器,因为该操作不记录单个行删除。在性能方面更快,因为它不保留任何日志。注意:与 Transaction 一起使用时,Delete 和 Truncate 都可以回滚。如果 Transaction 已完成,意味着已提交,那么我们无法回滚 Truncate 命令,但我们仍然可以从 Log 文件中回滚 Delete 命令,因为 delete write 将它们记录在 Log 文件中,以防将来需要从 log 文件中回滚。如果您有一个外键约束引用您要截断的表,即使引用表中没有数据,这也不起作用。这是因为外键检查是使用 DDL 而不是 DML 完成的。这可以通过暂时禁用表的外键约束来解决。删除表是一个记录操作。因此,每行的删除都会记录在事务日志中,这使得它变慢了。截断表也会删除表中的所有行,但它不会记录每一行的删除,而是记录表数据页的释放,这使得它更快。 ~ 如果您不小心使用删除/截断从表中删除了所有数据。您可以回滚已提交的事务。恢复上次备份并运行事务日志,直到删除/截断即将发生。


感谢@Lucas:他内联了内容。我只是把它放在一个引用中,以表明它来自不同的来源。
M
Mangal Pardeshi

这是我在 the difference between DELETE and TRUNCATE in SQL Server 上的详细回答

• 删除数据:首先,两者都可用于从表中删除行。但 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 通过解除分配用于存储表数据的数据页来移除数据,并且仅在事务日志中记录页解除分配。

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

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

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

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

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

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


嗨 Mangal - 感谢您的回答,特别是针对 SQL*Server 特定问题。你认为你可以将这些观点与被接受的社区 Wiki 答案整合在一起吗?
是的,但如何以及在哪里?对不起,我是新来的。
“因此,如果您想保留身份计数器,请使用 DELETE”您可以使用 DECLARE @ai as bigint SET @ai =IDENT_CURRENT('tablename') TRUNCATE TABLE tablename DBCC checkident('tablename', RESEED, @ai)
佚名

在 SQL Server 2005 中,我相信您可以回滚截断


C
Community

DELETE DELETE 命令用于从表中删除行。 WHERE 子句可用于仅删除某些行。如果未指定 WHERE 条件,则将删除所有行。执行 DELETE 操作后,您需要 COMMIT 或 ROLLBACK 事务以使更改永久化或撤消它。请注意,此操作将触发表上的所有 DELETE 触发器。 TRUNCATE TRUNCATE 从表中删除所有行。该操作无法回滚,也不会触发任何触发器。因此,TRUCATE 速度更快,并且不像 DELETE 那样使用太多的撤消空间。 DROP DROP 命令从数据库中删除一个表。所有表的行、索引和权限也将被删除。不会触发任何 DML 触发器。该操作无法回滚。 DROP 和 TRUNCATE 是 DDL 命令,而 DELETE 是 DML 命令。因此 DELETE 操作可以回滚(撤消),而 DROP 和 TRUNCATE 操作不能回滚。

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


这是否会为当前的答案增加一些内容?
S
SQLnbe

如果包装在事务中,则 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

TRUNCATE vs. DELETE 是 SQL 面试中臭名昭著的问题之一。只要确保你向面试官正确解释它,否则它可能会让你失去工作。问题是没有多少人知道,所以如果你告诉他们 YES Truncate 可以回滚,他们很可能会认为答案是错误的。


w
westyside

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


C
CaptainPicard

对原始答案的小修正 - 删除也会产生大量的重做(因为撤消本身受重做保护)。这可以从自动跟踪输出中看出:

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

它的旧线程,但根据我的理解,截断只会生成大量的重做日志,而删除会同时生成撤消和重做。
L
Luc M

删除

DELETE 是一个 DML 命令 DELETE 可以回滚 Delete = Only Delete- 所以可以回滚

截短

TRUNCATE 是一个 DDL 命令你不能在 TRUNCATE 中回滚,TRUNCATE 会永久删除记录 Truncate = Delete+Commit -so we can't roll back 你不能在 TRUNCATE 中使用条件(WHERE 子句)语法 – 截断表 [表]

欲了解更多详情,请访问

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


L
Learning

最大的区别是 truncate 是非记录操作,而 delete 是。

简单来说就是在数据库崩溃的情况下,truncate 操作的数据是无法恢复的,而 delete 则可以。

更多详情here


B
Bhushan Patil

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

SQL DELETE 语句的语法是:

DELETE FROM table_name [WHERE 条件];

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


O
Oskar

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


J
Jordan Ogren

它很方便的一个重要原因是,当您需要刷新数百万行表中的数据,但又不想重建它时。 “删除 *” 将永远持续,而 Truncate 的性能影响可以忽略不计。


佚名

无法通过 dblink 执行 DDL。


n
nathan

我会评论 matthieu 的帖子,但我还没有代表...

在 MySQL 中,自动增量计数器使用 truncate 重置,但不会使用 delete 重置。


u
user2587360

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

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


R
Robert

截断也可以在这里回滚示例

begin Tran
delete from  Employee

select * from Employee
Rollback
select * from Employee

w
wpzone4u

SQL中的截断和删除是两个用于从表中删除或删除数据的命令。尽管在本质上非常基本,但在使用之前熟悉细节之前,这两个 Sql 命令都会产生很多麻烦。如果需要删除太多数据而日志段不够用,则命令选择不正确可能会导致进程非常缓慢,甚至会炸毁日志段。这就是为什么知道何时在 SQL 中使用 truncate 和 delete 命令至关重要,但在使用这些命令之前,您应该了解 Truncate 和 Delete 之间的差异,并基于它们,我们应该能够找出 DELETE 何时是删除的更好选择data 或 TRUNCATE 应该用于清除表。

请参阅检查 click here


G
Gerald

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


A
Ali

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


M
Mykhailo Seniutovych

另一个特定于 microsoft sql server 的区别是使用 delete 您可以使用 output 语句来跟踪已删除的记录,例如:

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

您无法使用 truncate 执行此操作。


R
Rishish

Truncate 命令用于重新初始化表,它是一个 DDL 命令,删除表的所有行。而 DELETE 是一个 DML 命令,用于根据某些条件删除行或行集,如果没有指定条件然后此命令将从表中删除所有行。


关注公众号,不定期副业成功案例分享
关注公众号

不定期副业成功案例分享

领先一步获取最新的外包任务吗?

立即订阅