在sql存储过程中循环并删除游标

Posted

技术标签:

【中文标题】在sql存储过程中循环并删除游标【英文标题】:loop in sql stored procedure and removing cursors 【发布时间】:2015-05-26 23:25:17 【问题描述】:

我必须修改由其他人编写的存储过程。基本上,存储过程使用游标从表中获取数据,然后将该数据插入另一个表中。在从另一个表中获取代码时,它还会从另一个表中获取一些不同的列下面是我的代码:

 Declare data_cursor cursor for

    Select emp_no, emp_name, event_date, Test_no, Code, Test_result
      From test_table1
     ORDER by emp_no

declare
   @empNo   varchar(100),
   @emp_name varchar(2000),
   @eventDate  varchar(20),
   @TestNo     varchar(100),
   @Code       varchar(100),
   @TestReuslt  varchar(100),
   @ProcessName  varchar(100),
   @FileProcess   varchar(200),
   @TestProcess   varchar(100),
   @countA         int,
   @error_count int

SELECT @ProcessName = (select distinct userID from test_table1)
SELECT @FileProcess = 'EW' + @ProcessName 
Select @TestProcess  = (Select distinct userID from test_Table1) + 'TXT'
select @countA = 0

  BEGIN tran
     OPEN data_cursor  
     fetch data_cursor into
      @empNo  ,
      @emp_name ,
      @eventDate  ,
      @TestNo  ,  
      @Code      , 
      @TestReuslt
  while (@@FETCH_STATUS=0)
     begin
      insert into TESTTable2
            (
               empNum, empName, eventDate,TestNum, Code, TestResult, Testprocess,  ProcessName)
       values (@empNo, @emp_name, @eventDate , @TestNo , @Code, @TestReuslt, @TestProcess, @ProcessName)
   if @ ERROR > 0
            begin
                select @error_count = @error_count + 1
            end

        else
            set @record_id = @@Identity

        if @code like 'D%'
                  Insert into TESTTable3
            (testProcess, FileProcess, empNum)
                 values (@TestProcess,  @FileProcess, @empNo )
    if @@error > 0
            begin
                select @error_count = @error_count + 1
            end 

         set @countA = @countA + 1
       fetch data_cursor into
         fetch data_cursor into
      @empNo  ,
      @emp_name ,
      @eventDate  ,
      @TestNo  ,  
      @Code      , 
      @TestReuslt
if @ ERROR > 0
    BEGIN
        select @error_count = @error_count + 1
        end
    end 

     if @error_count > 0 
    begin
    rollback tran
    end
else

    begin /* @@error = 0 */
    commit tran

close data_cursor
deallocate data_cursor


     Insert into LOG_File
      (Name, Count, Processname)
       values ('Test1', @CountA,@ProcessName)

Select 'TotalCount' = @CountA

原因,我现在必须修改上面的存储过程是因为一些应用程序的变化,我从 test_table1 得到大约 50 个不同的用户 ID,所以上面的子查询(SELECT @ProcessName =(从 test_table1 中选择不同的用户 ID)没有工作。我怎样才能遍历上面存储的过程,以便每个@ProcessName 可以插入到表 TESTTable2 中,换句话说

我想一次传递每个 userId 并将其插入表 test_table1 和其他后续表中。我可以声明另一个游标来完成此操作,但我想知道是否有更好的方法来重写这个存储过程并且根本不使用游标。

由于我的应用程序更改,上面所有这三个语句都引发了错误:

SELECT @ProcessName = (select distinct userID from test_table1)
SELECT @FileProcess = 'EW' + @ProcessName 
Select @TestProcess  = (Select distinct userID from testTable1) + 'TXT'

我使用的是 sql server 2005。

任何帮助将不胜感激。

【问题讨论】:

真的不知道应该为 log_file 表做什么,因为它不在游标内,但我认为其余的会产生正确的结果 【参考方案1】:
declare @countA int=0

begin tran
begin try
    insert into TESTTable2(empNum, empName, eventDate,TestNum, Code, TestResult, Testprocess,  ProcessName)
        Select emp_no, emp_name, event_date, Test_no, Code, Test_result,userID+ 'TXT',userID
        From test_table1
        ORDER by emp_no

    SET @CountA=@@ROWCOUNT

    Insert into TESTTable3(testProcess, FileProcess, empNum)
        Select userID+ 'TXT','EW' + userID,emp_no
        From test_table1
        Where code like 'D%'
        ORDER by emp_no

    commit tran

    Insert into LOG_File(Name, Count, Processname) values ('Test1', @CountA,'@ProcessName')
end try
begin catch
    rollback tran

    SET @CountA =0
    Insert into LOG_File(Name, Count, Processname) values ('Test1', @CountA,'@ProcessName')

    SELECT ERROR_NUMBER() AS ErrorNumber,ERROR_MESSAGE() AS ErrorMessage
end catch

Select @CountA [TotalCount]

【讨论】:

上述代码的唯一问题是如果插入到 testTable2 失败,我不会收到错误消息。使用上面带有游标的存储过程,插入到 TestTable2 失败,然后我收到错误消息,告诉我插入失败的原因。现在,我只收到消息说(0 行受影响)。有什么办法,我尝试执行代码时会收到错误消息。

以上是关于在sql存储过程中循环并删除游标的主要内容,如果未能解决你的问题,请参考以下文章

数据库基础详解:存储过程、视图、游标、SQL语句优化以及索引

如何删除 MS SQL Server 存储过程中的 While 循环? [关闭]

一个Sql Server 的游标与循环嵌套的存储过程用例

在存储过程中的删除语句后使用游标[重复]

MySQL存储过程游标循环简单实例

SQL server2014数据库存储过程 实现游标循环读取 循环插入数据