SQL中TRUNCATE和DELETE的区别是什么?
如果你的答案是针对特定平台的,请注明。
SQL中TRUNCATE和DELETE的区别是什么?
如果你的答案是针对特定平台的,请注明。
当前回答
Truncate and Delete in SQL are two commands which is used to remove or delete data from table. Though quite basic in nature both Sql commands can create lot of trouble until you are familiar with details before using it. An Incorrect choice of command can result is either very slow process or can even blew up log segment, if too much data needs to be removed and log segment is not enough. That's why it's critical to know when to use truncate and delete command in SQL but before using these you should be aware of the Differences between Truncate and Delete, and based upon them, we should be able to find out when DELETE is better option for removing data or TRUNCATE should be used to purge tables.
参考资料请点击这里
其他回答
微软sql server的另一个不同之处在于,使用delete,你可以使用output语句来跟踪哪些记录被删除了,例如:
delete from [SomeTable]
output deleted.Id, deleted.Name
你不能用truncate这样做。
Truncate and Delete in SQL are two commands which is used to remove or delete data from table. Though quite basic in nature both Sql commands can create lot of trouble until you are familiar with details before using it. An Incorrect choice of command can result is either very slow process or can even blew up log segment, if too much data needs to be removed and log segment is not enough. That's why it's critical to know when to use truncate and delete command in SQL but before using these you should be aware of the Differences between Truncate and Delete, and based upon them, we should be able to find out when DELETE is better option for removing data or TRUNCATE should be used to purge tables.
参考资料请点击这里
删除
DELETE是一个DML命令 DELETE可以回退 Delete =仅删除-因此可以回滚 在DELETE中,可以使用WHERE子句编写条件 语法- Delete from [Table] where [Condition]
截断
TRUNCATE是一个DDL命令 不能在TRUNCATE中回滚,TRUNCATE将永久删除该记录 Truncate = Delete+Commit -这样我们就不能回滚 不能在TRUNCATE中使用条件(WHERE子句) 语法- Truncate table [table]
详情请浏览
http://www.zilckh.com/what-is-the-difference-between-truncate-and-delete/
对原始答案的一个小修正——删除也会产生大量的重做(因为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
下面是一些不同之处。我强调了特定于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;