2

我在存储过程中使用游标;我希望从我的 SP 中删除光标。请帮我想出一个解决方案,以解决如何避免游标语句使用动态的正常更新语句。

下面的例子:

  1. Update Tablename set columnname(variable) = value from table A join Table B on A.condition = B.Condition where name = 'Test'(variable) and age = 18(variable)

  2. Update Tablename set columnname(variable) = value from table A join Table B on A.condition = B.Condition where name = 'kumar'(variable) and age = 19(variable)

  3. Update Tablename set columnname(variable) = value from table A join Table B on A.condition = B.Condition where name = 'babu'(variable) and age = 30(variable)

这就是我的光标的工作方式。300组合动态从表中挑选数据并更新到主表中

我试图取出游标,更新语句应该与此类似,而不是编写 300 个更新语句,我想编写一个更新,所有 300 个组合都应该执行。

以下是我需要此解决方案的代码:

BEGIN
  DECLARE @Type VARCHAR(100)           
  DECLARE @TargetColumn VARCHAR(100)           
  DECLARE @SourceColumn VARCHAR(100)           
  DECLARE @SQL varchar(max)        

  DECLARE a_cursor CURSOR STATIC           
  FOR          
  SELECT [Type],[SourceColumn],[TargetColumn] FROM  ref.tblEdsMap        
  GROUP BY [Type],[SourceColumn],[TargetColumn]         
  OPEN a_cursor          
  FETCH NEXT FROM a_cursor INTO @Type,@SourceColumn,@TargetColumn      
  WHILE @@FETCH_STATUS = 0          
  BEGIN          


  SET @SQL = 'UPDATE  GCT SET GCT.' + @TargetColumn + ' = map.[TargetValue]       
   from  EdsMap map      
   JOIN Table GCT      
   ON GCT.' + @SourceColumn + ' = map.[SourceValue]       
   where map.[Type]=''' + @Type + ''' and map.SourceColumn=''' + @SourceColumn+ ''''       
  Exec (@SQL)        
  PRINT @SQL        
  FETCH NEXT FROM a_cursor INTO @Type,@SourceColumn,@TargetColumn      
  END          
  CLOSE a_cursor          
  DEALLOCATE a_cursor       
END
4

3 回答 3

1

对于此类问题,我更喜欢行连接操作,而不是使用显式游标或巧妙地伪装成 while 循环的游标。

DECLARE @cmd NVARCHAR(MAX) = N'';

SELECT @cmd += N'
   UPDATE GCT 
     SET GCT.' + QUOTENAME(TargetColumn) + ' = map.TargetValue     
     FROM dbo.EdsMap AS map 
     INNER JOIN dbo.Table AS GCT      
     ON GCT.' + QUOTENAME(SourceColumn) + ' = map.SourceValue    
   WHERE map.[Type] = ''' + [Type] + ''' 
   AND map.SourceColumn = ''' + [SourceColumn]+ ''';'
FROM ref.tblEdsMap
GROUP BY [Type], SourceColumn, TargetColumn;

EXEC sp_executesql @sql;
于 2013-07-25T04:18:13.770 回答
0

当我过去完成这些工作时,我通常会编写一个事务来包含所需的每个更新。像这样的东西:

    CREATE TABLE #targets ([Type] VARCHAR(255),[SourceColumn] VARCHAR(255),[TargetColumn] VARCHAR(255));

    INSERT INTO #targets
            ( [Type], [SourceColumn], [TargetColumn] )       
    SELECT [Type],[SourceColumn],[TargetColumn] FROM  ref.tblEdsMap        
      GROUP BY [Type],[SourceColumn],[TargetColumn]; 

    DECLARE @sql VARCHAR(MAX);

    SET @sql = 'BEGIN TRAN'  + CHAR(10) + CHAR(13);

    SELECT @sql = @sql + 
    'UPDATE  GCT SET GCT.' + [TargetColumn] + ' = map.[TargetValue]       
       from  EdsMap map      
       JOIN Table GCT      
       ON GCT.' + [SourceColumn] + ' = map.[SourceValue]       
       where map.[Type]=''' + [Type] + ''' and map.SourceColumn=''' + [SourceColumn]+ ''';' + CHAR(10) + CHAR(13)
    FROM #targets   

    SELECT @sql = @sql + 'COMMIT TRAN'

    PRINT @sql

    Exec (@SQL) 

更新语句仍然是相同的,即每个组合都会获得一个更新。但是现在您作为一个事务批次运行。您可能更喜欢动态 SQL,因此您只有一个更新语句,但根据我的经验,以这种方式获取错误更新太容易了。

这样做可能不会比游标快。您必须进行测试才能确定。在我使用这种方法的示例中,它通常是一种更快的方法。

于 2013-07-24T19:18:04.253 回答
-2

尝试使用表变量和WHILE循环代替,如下所示:

 BEGIN

 DECLARE @Type VARCHAR(100)           
 DECLARE @TargetColumn VARCHAR(100)           
 DECLARE @SourceColumn VARCHAR(100)           
 DECLARE @SQL varchar(max)        

 DECLARE @SomeTable TABLE
 (
   ID int IDENTITY (1, 1) PRIMARY KEY NOT NULL,
   Type varchar(100),
   SourceColumn varchar(100),
   TargetColumn varchar(100)
 )

 DECLARE @Count int, @Max int

 INSERT INTO @SomeTable (Type, SourceColumn, TargetColumn)
 SELECT [Type],[SourceColumn],[TargetColumn]
 FROM  ref.tblEdsMap        
 GROUP BY [Type],[SourceColumn],[TargetColumn]

 SELECT @Count = 1, @Max = COUNT(ID)
 FROM @SomeTable

 WHILE @Count <= @Max
 BEGIN

   SELECT
        @Type = Type, 
        @SourceColumn = SourceColumn, 
        @TargetColumn = TargetColumn
   FROM @SomeTable
   WHERE ID = @Count  

   -- Your code
   SET @SQL = 'UPDATE  GCT SET GCT.' + @TargetColumn + ' = map.[TargetValue]       
   from  EdsMap map      
   JOIN Table GCT      
   ON GCT.' + @SourceColumn + ' = map.[SourceValue]       
   where map.[Type]=''' + @Type + ''' and map.SourceColumn=''' + @SourceColumn+ ''''       
   Exec (@SQL)        
   PRINT @SQL        

   SET @Count = @Count + 1

 END     -- while

 END
于 2013-07-24T17:54:33.170 回答