如何在存储过程中替换游标以在 MS SQL 中更快地执行?

How to replace cursor inside Stored Procedure for faster Execution in MS SQL?

我已经写了下面的分割字符串的代码,但是执行起来需要很长时间。请帮助我重新编写代码以优化查询。我努力寻找结果,但我不知道如何应用逻辑来替换光标。

declare @table as nvarchar(50),@column as nvarchar(max),@delimiter
as nvarchar(1),@tablekey as nvarchar(max)

BEGIN  
SET NOCOUNT ON;  
 set @table='QAT_Tsentences'
 set @column='SentenceElID'
 set @delimiter='|'
 set @tablekey='ID'

 declare @sql as nvarchar(max), @tabkey as nvarchar(max),  @txt as 
 nvarchar(1000), @txtSplitted as nvarchar(255)  
 DECLARE @pos integer--, @delimiter as nchar(1)  
 DECLARE @Leftpiece nvarchar(255), @Rightpiece as nvarchar(255)  


 CREATE TABLE #t(tablekey  nvarchar(max), txt nvarchar(1000))  
 set @sql= 'INSERT #t select '+@tablekey+','+@column+' from '+@table+' where 
 '+@column+' is not null'  

  exec(@sql)  

  drop table QAT_txtsplitted  
  CREATE TABLE QAT_txtsplitted(tablekey  nvarchar(max), txt [nvarchar] 
 (max), txtSplitted [nvarchar](max), ID INT NOT NULL IDENTITY(1,1))  



  DECLARE c1 CURSOR   
  FOR  
   SELECT tablekey, txt  
    FROM #t  

   OPEN c1  

   FETCH NEXT FROM c1  
   INTO @tabkey,@txt  
    While (@@Fetch_status = 0)  
    BEGIN   

    SET @Rightpiece = @txt  
    IF RIGHT(RTRIM(@Rightpiece),1) <> @delimiter  
    SET @Rightpiece = @Rightpiece  + @delimiter  
    SET @pos =  CHARINDEX(@delimiter, @Rightpiece)  

    WHILE @pos <> 0   
    BEGIN  
    SET @Leftpiece = LEFT(@Rightpiece, @pos - 1)  
     INSERT INTO  QAT_txtsplitted (tablekey,txt,txtsplitted) VALUES  
      (@tabkey,@txt, @Leftpiece);  
      SET @Rightpiece = STUFF(@Rightpiece, 1, @pos, '')  
      SET @pos =  CHARINDEX(@delimiter, @Rightpiece)  
       END  
       FETCH NEXT FROM c1  
       INTO @tabkey,@txt  

       END  

  CLOSE c1  
     DEALLOCATE c1  
     drop table #t  
     nchar(1),@tablekey as decimal(15))  
     print 'table results : QAT_txtsplitted'  

     END 

请在下面找到我尝试拆分特定表键的结果。

游标在为基于集合的操作而设计的 SQL 服务器中可能表现不佳。有一些方法可以通过应用额外的参数来提高游标的性能,这些参数 can be read about here. 如果您只想按顺序单步执行游标,那么您可以通过使用 LOCAL FAST_FORWARD 参数来减轻很多开销。

DECLARE C1 CURSOR LOCAL FAST_FORWARD FOR <your query>

另一种性能更好的方法是 while 循环。

DECLARE @cnt INT = 0;
Declare @t_CNT = Select Count(*) from t 
WHILE @cnt < @t_CNT
BEGIN
 // do your work here
   SET @cnt = @cnt + 1;
END;

这是我写的用于删除游标的 SP 的一部分

BEGIN
    DECLARE @Modules TABLE
    (
        ID INT IDENTITY(1,1)
        , ModuleId INT
        , ModuleShortName NVARCHAR(256)
        , ModuleTableName NVARCHAR(260)
    )

    INSERT INTO @Modules select ModuleId,ModuleShortName ,ModuleTableName  from Mods

    DECLARE @Count INT, @Counter INT, @ModuleId INT, @ModuleTableName NVARCHAR(260)
    SELECT @Count = COUNT(*) FROM @Modules m
    SET @Counter = 1



    WHILE @Counter <= @Count
    BEGIN
        SELECT @ModuleId = ModuleId, @ModuleTableName = ModuleTableName FROM @Modules m WHERE ID = @Counter -- extracting values from the table by counternum

         -- do something with data
        -- puttin inner logic


        SET @Counter = @Counter + 1
    END