【SQL Server学习笔记】Delete 语句、Output 子句、Merge语句

时间:2023-03-08 16:19:20

原文:【SQL Server学习笔记】Delete 语句、Output 子句、Merge语句


DELETE语句


  1. --建表
  2. select * into distribution
  3. from sys.objects
  4. --1.当delete语句要关联其他表时与update语句类似,可参考上面update语句的写法
  5. --2.truncate table语句删除行比delete快很多,不过必须一次删除所有的行(没有where子句)
  6. --之所以快是因为记录的日志很少,采用表级别锁。
  7. --如果表中有IDENTITY列,会被重置为列定义的种子值4、TOP--1.在一个事务中删除所有记录,此表的记录有1000w条
  8. delete from distribution
  9. --2.通过top每次只删除1000条记录
  10. while (select COUNT(*) from distribution) > 0
  11. begin
  12. delete top (1000)
  13. from distribution
  14. end
  15. /*===============================================================
  16. 比较1和2(不只限于delete,还包括update、insert),2有以下优点:
  17. 1.每次操作1000条,就提交一次,那么产生少量的日志,使日志空间更容易被重用;
  18. 如果一次删除大量记录,而产生的大量日志可能比整个日志文件还大,
  19. 那么会引起日志文件的自动增长,会影响性能
  20. 2.分块操作记录,一次锁住更少的记录,占用更少的锁资源,
  21. 锁定时间更短,操作完成后这些记录可被其他进程访问,并发性更好
  22. =================================================================*/

OUTPUT子句


  1. create table t(vid int not null,pic varchar(10) not null)
  2. insert into t
  3. values(1,'abc'),
  4. (2,'def'),
  5. (3,'hjkl')
  6. --output必须写在where子句之前
  7. update t
  8. set pic = 'xyz' --更新操作由删除+添加组合的
  9. output deleted.vid, --删除的记录
  10. deleted.pic,
  11. inserted.vid, --添加的记录
  12. inserted.pic
  13. where vid < 100
  14. --output写在values之前
  15. insert into t(vid,pic)
  16. output inserted.*
  17. values(5,'mn')
  18. declare @temp table(vid int,pic varchar(10))
  19. delete from t
  20. output deleted.vid, --引用所有字段deleted.*
  21. deleted.pic into @temp
  22. where vid < 100

output子句的一个应用,由于主表和附表是级联删除的,需要实现删除主表记录时,自动保存主表和附表中相关重要字段的值:


  1. --创建主表
  2. create table t1(id int primary key,v varchar(10))
  3. --创建附表,级联删除
  4. create table t2
  5. (
  6. idd int,
  7. id int foreign key references t1(id) on delete cascade,
  8. vv varchar(20)
  9. )
  10. insert into t1
  11. select 1,'a' union all
  12. select 2,'b'
  13. insert into t2
  14. select 1,1,'www' union all
  15. select 1,2,'****'
  16. --创建存储删除的t1表的字段
  17. create table temp_t1_delete(id int,v varchar(10))
  18. --创建存储删除的t2表的字段
  19. create table temp_t2_delete(id int,vv varchar(20))
  20. go
  21. --创建表t2的delete触发器
  22. create trigger dbo.trigger_t2_delete
  23. on dbo.t2
  24. for delete
  25. as
  26. begin
  27. insert into temp_t2_delete(id,vv)
  28. select id,vv
  29. from deleted
  30. end
  31. go
  32. --删除主表记录,自动把删除的主表记录,保存在temp_t1_deletei表中
  33. delete from t1
  34. output deleted.id, --引用所有字段deleted.*
  35. deleted.v into temp_t1_delete
  36. where id = 1
  37. --查询已删除的记录
  38. select *
  39. from temp_t1_delete t1
  40. left join temp_t2_delete t2
  41. on t1.id = t2.id
  42. /*
  43. id v id vv
  44. 1 a 1 www
  45. */

MERGE语句


  1. create table t_org(org_id int,
  2. v1 varchar(20),
  3. v2 varchar(30));
  4. insert into t_org
  5. select 1,'org1',''
  6. union all
  7. select 2,'org2','name2'
  8. union all
  9. select 3,'org3','name3'
  10. union all
  11. select 4,'org4','name4'
  12. union all
  13. select 5,'org5','name5'
  14. create table t_store(org_id int,
  15. v1 varchar(20),
  16. v2 varchar(30));
  17. insert into t_store
  18. select 1,'org1',''
  19. union all
  20. select 2,'org2-t','name2-t'
  21. union all
  22. select 3,'org3-t','name3-t'
  23. union all
  24. select 4,'org4-t','name4-t'
  25. union all
  26. select 5,'org5-t','name5-t'
  27. union all
  28. select 6,'org6-t','name6-t'
  29. union all
  30. select 7,'org7-t','name7-t'
  31. --生成临时表
  32. select * into #t_org from t_org
  33. select * into #t_store from t_store
  34. --定义表变量
  35. declare @delete_insert_t_org table(
  36. change nvarchar(100),
  37. org_id int,v1 varchar(20),v2 varchar(30), --删除的
  38. org_id_t int,v1_t varchar(20),v2_t varchar(30)) --添加的
  39. ;with mm --作为merge语句中using的内部派生表
  40. as
  41. (
  42. select m.org_id,
  43. m.v1,
  44. m.v2
  45. from #t_store m
  46. where m.org_id >1
  47. )
  48. --注意:表 with(tablock),另外通过top关键字只是处理3条记录
  49. merge top (3) into #t_org with (tablock) as b
  50. using (
  51. select *
  52. from mm with (tablock) --引用上面CTE公用表表达式产生的内部派生表
  53. ) m
  54. on m.org_id = b.org_id --为了区分是否需要修改,可以增加一个字段来区分,
  55. --但是这个字段不应该作为关联条件,
  56. --因为会导致接下来运行的merge分块语句把刚才目标表中update过的那条记录,
  57. --重复插入目标表中,而是写在when的条件中
  58. when matched and b.v1 <> m.v1 and isnumeric(m.org_id) = 1 --可以在这里写:区分字段过滤条件
  59. then update set v1 = m.v1,v2 = m.v2
  60. when not matched by target --目标表中没有
  61. then insert (org_id,v1,v2) values(m.org_id,m.v1,m.v2) --不可通过values关键字一次添加多列
  62. when not matched by source --源表中没有
  63. then delete
  64. output $action, --操作:delete、insert、update
  65. inserted.org_id,
  66. inserted.v1,
  67. inserted.v2 , --可改为inserted.*
  68. deleted.org_id,
  69. deleted.v1,
  70. deleted.v2 --可改为deleted.*
  71. INTO @delete_insert_t_org --output的输出放入表变量中
  72. --关联提示
  73. option (loop join); --注意:merge必须以分号结尾
  74. select * from @delete_insert_t_org
【SQL Server学习笔记】Delete 语句、Output 子句、Merge语句
【SQL Server学习笔记】Delete 语句、Output 子句、Merge语句
发布了416 篇原创文章 · 获赞 135 · 访问量 94万+