SQL Cursor 游标的使用

时间:2022-05-08 04:46:03

Contents

SQL Cursor 游标的使用

这两天在做新老系统间的data migration,接触到sql的游标,记录总结一下。

我们的需求是要求map多张表,并把计算结果分别更新到一张目标表中, 新旧系统要做A/B Testing, 所以当旧表有任何更新,比如新增,删除,改动, 都要更新到新表中。

原本我选择的方案是采用批量Insert, 但碰到一个需要插入map关系的表, 其中一个field是另外一张表刚刚插入数据的id, 因此只能用循环来解决。 看了一圈SQL的for循环,实现起来略显费力。当然也有用while do或临时表等其他解决方案,欢迎发邮件探讨,这里分享一下游标的使用心得。

以我的理解,可以把游标想象成一个指针,我们使用一个指针的时候需要做的事情:

  • 声明指针
  • 把指针指向一个地址
  • 获取指针内容
  • 移动指针指向新的地址

这样理解起来游标就比较方便, 下面举个例子来说明游标的使用方法:

      
       1
      
      
       2
      
      
       3
      
      
       4
      
      
       5
      
      
       6
      
      
       7
      
      
       8
      
      
       9
      
      
       10
      
      
       11
      
      
       12
      
      
       13
      
      
       14
      
      
       15
      
      
       16
      
      
       17
      
      
       18
      
      
       19
      
      
       20
      
      
       21
      
      
       22
      
      
       23
      
      
       24
      
      
       25
      
      
       26
      
      
       27
      
      
       28
      
      
       29
      
      
       30
      
      
       31
      
      
      
       DECLARE @vm_bucket_id 
       bigint, @
       group_id 
       bigint, @
       name 
       varchar(
       50)
      
      
       --声明游标 
      
      
       DECLARE MyCursor 
       CURSOR 
      
      
       --查询出数据结果集合,游标将指向这个集合 
      
      
       FOR (
       SELECT 
       id, 
       group_id, 
       name 
       FROM dbo.vm_bucket 
       WHERE 
       id 
       NOT 
       IN(
      
      
       SELECT object_id 
       from dbo.resource_group_map 
       where 
       object=
       29)) 
       ORDER 
       BY 
       id 
      
      
       --打开游标 
      
      
       OPEN MyCursor 		
      
      
       --从游标中取出内容放到声明好的变量中 
      
      
       FETCH 
       NEXT 
       FROM MyCursor 
       INTO @vm_bucket_id, @
       group_id, @
       name
      
      
       --对取出的数据进行判断和处理
      
      
       WHILE @@FETCH_STATUS = 
       0
      
      		
       BEGIN
      
      			
       --插入数据
      
      			
       INSERT 
       INTO dbo.resource_group
      
      
       			(
       name, 
       group_id, user_id, created_date)
      
      			
       VALUES (@
       name, @
       group_id, 
       0, 
       getutcdate())
      
      		
      
      			
       --把刚刚插入数据的id作为结果插入到另一张表
      
      			
       INSERT 
       INTO dbo.resource_group_map
      
      
       			(resource_group_id, 
       object, object_id)
      
      			
       VALUES (@@
       identity, 
       29, @vm_bucket_id)
      
      
      			
       --读取下一行
      
      			
       FETCH 
       NEXT 
       FROM MyCursor 
       INTO @vm_bucket_id, @
       group_id, @
       name
      
      		
       END
      
      
       --关闭游标
      
      
       CLOSE MyCursor
      
      
       --释放游标
      
      
       DEALLOCATE MyCursor
      



总结: 游标是一种较易理解易读的程序写作模型,但如果使用不当,很容易扼杀性能,谨慎使用。

原文:大专栏  SQL Cursor 游标的使用