如何在存储过程中替换游标以在 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
我已经写了下面的分割字符串的代码,但是执行起来需要很长时间。请帮助我重新编写代码以优化查询。我努力寻找结果,但我不知道如何应用逻辑来替换光标。
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