Stored procedures 在存储过程中使用光标
在MS SQL 2016存储过程中,我有以下极慢的代码(我认为它陷入了一个永无止境的循环): 此过程只是一个维护过程,不会经常运行,但运行时最好只需几秒钟。其目的是在一个表中规范化ADMIN_API_Master_Members_List表中每个逗号分隔值的一条记录,并将其与程序代码、成员ID和DBID一起放入ADMIN_API_PMID_PROGRAM_CODE_HOLDING_表中 主表中只有大约150条记录,逗号分隔的字符串可能有5个值。我接受其他解决方案Stored procedures 在存储过程中使用光标,stored-procedures,sql-server-2016,Stored Procedures,Sql Server 2016,在MS SQL 2016存储过程中,我有以下极慢的代码(我认为它陷入了一个永无止境的循环): 此过程只是一个维护过程,不会经常运行,但运行时最好只需几秒钟。其目的是在一个表中规范化ADMIN_API_Master_Members_List表中每个逗号分隔值的一条记录,并将其与程序代码、成员ID和DBID一起放入ADMIN_API_PMID_PROGRAM_CODE_HOLDING_表中 主表中只有大约150条记录,逗号分隔的字符串可能有5个值。我接受其他解决方案 提前感谢无限循环的原因可能是循环
提前感谢无限循环的原因可能是循环中没有“Fetch next” 请尝试以下方法:
@DBID Integer
AS
BEGIN
DECLARE TagCursor CURSOR FOR SELECT MemberID
FROM ADMIN_API_Master_Members_List
WHERE DBID= @DBID AND Len(Pending) > 0
DECLARE @ProgramCode VARCHAR(10)
DECLARE @Values VARCHAR(MAX)
DECLARE @tag nvarchar(10)
OPEN TagCursor
FETCH NEXT FROM TagCursor INTO @tag
WHILE (@@FETCH_STATUS = 0)
BEGIN
SELECT @ProgramCode = Program_Code, @Values= Pending FROM ADMIN_API_Master_Members_List WHERE MemberID= @tag
DELETE FROM ADMIN_API_PMID_PROGRAM_CODE_HOLDING_TABLE
WHERE (MemberID =@tag)
INSERT INTO ADMIN_API_PMID_PROGRAM_CODE_HOLDING_TABLE ( ProgramCode, MemberID, DBID, PMID)
SELECT @ProgramCode, @tag, @DBID , Value FROM STRING_SPLIT(@Values, ',')
FETCH NEXT FROM TagCursor INTO @tag
END
CLOSE TagCursor
DEALLOCATE TagCursor
END
无限循环的原因可能是循环中没有“fetchnext” 请尝试以下方法:
@DBID Integer
AS
BEGIN
DECLARE TagCursor CURSOR FOR SELECT MemberID
FROM ADMIN_API_Master_Members_List
WHERE DBID= @DBID AND Len(Pending) > 0
DECLARE @ProgramCode VARCHAR(10)
DECLARE @Values VARCHAR(MAX)
DECLARE @tag nvarchar(10)
OPEN TagCursor
FETCH NEXT FROM TagCursor INTO @tag
WHILE (@@FETCH_STATUS = 0)
BEGIN
SELECT @ProgramCode = Program_Code, @Values= Pending FROM ADMIN_API_Master_Members_List WHERE MemberID= @tag
DELETE FROM ADMIN_API_PMID_PROGRAM_CODE_HOLDING_TABLE
WHERE (MemberID =@tag)
INSERT INTO ADMIN_API_PMID_PROGRAM_CODE_HOLDING_TABLE ( ProgramCode, MemberID, DBID, PMID)
SELECT @ProgramCode, @tag, @DBID , Value FROM STRING_SPLIT(@Values, ',')
FETCH NEXT FROM TagCursor INTO @tag
END
CLOSE TagCursor
DEALLOCATE TagCursor
END
我还没有对此进行测试,但正如我在评论中提到的,使用
光标
是个坏主意;由于SQL Server擅长基于集合的方法而不是迭代任务(后者是游标),因此它们天生就很慢
我怀疑这可以实现您想要的答案,并且避免了光标
:
CREATE PROC YourProc @DBID integer
AS
BEGIN
DECLARE @Deleted table (ProgramCode varchar(10),
[Value] varchar(MAX),
Tag nvarchar(10));
DELETE HT
OUTPUT deleted.Program_Code,
deleted.Pending,
deleted.MemberID
INTO @Deleted (ProgramCode,
[Value],
Tag)
FROM ADMIN_API_PMID_PROGRAM_CODE_HOLDING_TABLE AS HT
JOIN ADMIN_API_Master_Members_List AS MML ON HT.MemberID = MML.MemberID
WHERE MML.[DBID] = @DBID
--AND LEN(Pending) > 0; --Changed this to below to be SARGable, as only a string with the value '' will have a length of 0.
AND Pending != '';
INSERT INTO ADMIN_API_PMID_PROGRAM_CODE_HOLDING_TABLE (ProgramCode,
MemberID,
DBID,
PMID)
SELECT D.ProgramCode,
D.Tag,
@DBID,
SS.Value
FROM @Deleted AS D
CROSS APPLY STRING_SPLIT(D.[Value], ',') AS SS;
END;
我还没有对此进行测试,但正如我在评论中提到的,使用光标
是个坏主意;由于SQL Server擅长基于集合的方法而不是迭代任务(后者是游标),因此它们天生就很慢
我怀疑这可以实现您想要的答案,并且避免了光标
:
CREATE PROC YourProc @DBID integer
AS
BEGIN
DECLARE @Deleted table (ProgramCode varchar(10),
[Value] varchar(MAX),
Tag nvarchar(10));
DELETE HT
OUTPUT deleted.Program_Code,
deleted.Pending,
deleted.MemberID
INTO @Deleted (ProgramCode,
[Value],
Tag)
FROM ADMIN_API_PMID_PROGRAM_CODE_HOLDING_TABLE AS HT
JOIN ADMIN_API_Master_Members_List AS MML ON HT.MemberID = MML.MemberID
WHERE MML.[DBID] = @DBID
--AND LEN(Pending) > 0; --Changed this to below to be SARGable, as only a string with the value '' will have a length of 0.
AND Pending != '';
INSERT INTO ADMIN_API_PMID_PROGRAM_CODE_HOLDING_TABLE (ProgramCode,
MemberID,
DBID,
PMID)
SELECT D.ProgramCode,
D.Tag,
@DBID,
SS.Value
FROM @Deleted AS D
CROSS APPLY STRING_SPLIT(D.[Value], ',') AS SS;
END;
为什么首先要使用光标?游标天生就是慢的。为什么不使用基于集合的方法?为什么首先使用光标?游标天生就是慢的。为什么不使用基于集合的方法呢?太棒了——效果很好。我已经起床太多小时了,从来没有看到错过了什么。谢谢这个网站上的人great@user1314159我仍然建议不要使用光标
。它们并不是SQL Server所擅长的。太棒了——工作起来很有魅力。我已经起床太多小时了,从来没有看到错过了什么。谢谢这个网站上的人great@user1314159我仍然建议不要使用光标
。它们不是SQL Server擅长的。好的,我能理解-谢谢,两个答案都有目的。好的,我能理解-谢谢,两个答案都有目的