• Sql Server在存储过程里面使用游标遍历一个表


    前:转自[https://www.cnblogs.com/SysoCjs/p/9842178.html]

    文章很详细,就转过来收藏啦,以下是正文

    这里关于SqlServer有两个知识点:一个是使用游标遍历表,另一个是使用if not exists的sql语句进行插入。

    一、使用游标遍历表

      这个表可以是数据库的表,也可以是外面DataTable类型的参数传进去,使用游标可以概括为以下步骤:声明游标、打开游标、读取数据、操作数据、读取数据、关闭游标、释放游标。

    二、在insert语句使用if not exits

      使用了if not exists的语句的insert操作,意思是,在找不到相关数据时才进行insert操作。不同数据库,有不同的使用语法。

    下面是创建存储过程:

    USE [CapacityManagement]
    GO
    
    /****** Object:  StoredProcedure [dbo].[USP_uploadResGpMaster]    Script Date: 2018/10/24 10:09:03 ******/
    SET ANSI_NULLS ON
    GO
    
    SET QUOTED_IDENTIFIER ON
    GO
    

    --创建一张表,用来接收C#程序传过来的DataTable对象
    --注意,这张表的字段必须跟传过来的DataTable对象的属性一致,名字可以不同

    create type GS_Master as table
    (
    ResGp varchar(10),
    Plant varchar(12),
    Dept varchar(12),
    Descrip nvarchar(50),
    Step_mapping varchar(10),
    CreateDate datetime,
    CreateBy char(8),
    ChangeDate datetime,
    ChangeBy char(8)
    )
    
    go
    
    CREATE PROCEDURE [dbo].[USP_uploadMaster] @Master GS_Master readonly,@OperationType nvarchar(3) 
    AS
    BEGIN    
        
        SET NOCOUNT ON;
        begin try
        begin transaction
        if(@OperationType ='A')
    --声明一些local变量,用于接收查询表得到的数据,以便操作
        declare @ResGp varchar(10),
                @Plant varchar(12),
                @Dept varchar(12),
                @Descrip nvarchar(50),
                @Step_mapping varchar(10),
                @CreateDate datetime,
                @CreateBy char(8),
                @ChangeDate datetime,
                @ChangeBy char(8),
                @master_id int
          begin
           --一、声明游标
           declare master_cursor cursor for select * from @Master
           --二、打开游标
           open master_cursor
           --三、取第一条数据
           fetch next from master_cursor 
                      into @ResGp,
                            @Plant,
                            @Dept,
                            @Descrip,
                            @Step_mapping,
                            @CreateDate,
                            @CreateBy,
                            @ChangeDate,
                            @ChangeBy 
           while @@FETCH_STATUS = 0
           begin
            --四、操作数据,先操作[ResGp_Master],后操作[Step_ResGp_Maping]
                --1、操作[ResGp_Master]
            SELECT @master_id=id FROM [CapacityManagement].[dbo].[ResGp_Master] 
                                    where resgp = @ResGp
                                    and    plant = @Plant
                                    and    dept = @Dept
    
            update [CapacityManagement].[dbo].[ResGp_Master]
            set ChaDate = @ChangeDate,
                ChaBy = @ChangeBy,
                ResGpDesc = @Descrip
            where id = @master_id
            
            IF NOT EXISTS (SELECT id FROM [CapacityManagement].[dbo].[ResGp_Master] WHERE id = @master_id)  
            INSERT INTO [CapacityManagement].[dbo].[ResGp_Master] (ResGp, Dept, CreDate, CreBy, ChaDate, ChaBy, ResGpDesc, plant)
            values(@ResGp, @Dept, @CreateDate, @CreateBy, @ChangeDate, @ChangeBy, @Descrip, @Plant)
    
                --2、操作[Step_ResGp_Maping]
            update [CapacityManagement].[dbo].[Step_ResGp_Maping]
            set ChaDate = @ChangeDate,
                ChaBy = @ChangeBy
            where Master_id = @master_id
            and step = @Step_mapping
    
            if not exists(select master_id from [CapacityManagement].[dbo].[Step_ResGp_Maping] where Master_id = @master_id    and step = @Step_mapping)
            insert into [CapacityManagement].[dbo].[Step_ResGp_Maping](step, resgp, CreDate, CreBy, ChaDate, ChaBy, Master_id)
            values(@Step_mapping, @ResGp, @CreateDate, @CreateBy, @ChangeDate, @ChangeBy, @master_id)
    
            --五、取下一条数据
            fetch next from master_cursor 
                      into @ResGp,
                            @Plant,
                            @Dept,
                            @Descrip,
                            @Step_mapping,
                            @CreateDate,
                            @CreateBy,
                            @ChangeDate,
                            @ChangeBy 
           end      
           --六、关闭游标
           close master_cursor
           --七、释放游标
           deallocate master_cursor 
          end
          
         commit transaction
        end try 
        begin catch
        select ERROR_MESSAGE() as errorMessage
        rollback transaction
        end catch
    
    END
    GO
    

    注释也是够详细了,操作数据那个过程,业务需求是对一堆数据进行插入,如果该数据已经存在,就进行更新,如果属于新数据,那么就进行插入(所以博主想到的是先遍历全部根据主键进行update,再根据主键查找是否存在该数据,若没有,则插入新数据),其实读者可以不细看,因为操作过程是根据业务需求,这里主要讲解游标的使用。

    值得留意的一点:存储过程创建一个table类型的变量是用来存储程序传过来的DataTable对象,不仅字段个数要与DataTable的列数一致,类型也要特别注意,假设如果将DataTable的非数字列传给table类型里面的int类型字段,则该存储过程无法执行,会抛出异常。

    注意:使用游标时,代码里使用一些局部变量存放查找的值(如@Master_id),如果第一次循环,@Master_id可以通过select查找到值,到了第二次select时却没有查找到值,那么@Master_id这个局部变量在第二次的循环里面的值不是null,也不是0或"",反而是第一次循环的值(即上一次循环的值)

  • 相关阅读:
    【Python】错误、调试和测试
    【c++ primer, 5e】函数指针
    【英语学习】【17/4/1】
    【c++ primer, 5e】函数匹配
    FIRST GAME.
    【Thinking in Java, 4e】访问权限控制
    【c++ primer, 5e】特殊用途语言特性
    Top-Down笔记 #01# 计算机网络概述
    NHibernate之映射文件配置说明
    Web Service 部署到IIS服务器
  • 原文地址:https://www.cnblogs.com/fmy-hmfy/p/12772273.html
Copyright © 2020-2023  润新知