Использование курсора в хранимой процедуре - PullRequest
0 голосов
/ 31 мая 2019

У меня следующий код чрезвычайно медленный код в хранимой процедуре MS SQL 2016 (я думаю, что он застрял в бесконечном цикле):

@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, ',')       
     END

      CLOSE TagCursor
      DEALLOCATE TagCursor 
END

Эта процедура является только процессом обслуживания и небегать очень часто, но когда это произойдет, было бы неплохо занять всего несколько секунд.Цель состоит в том, чтобы нормализовать в таблице одну запись для каждого значения, разделенного запятыми в таблице ADMIN_API_Master_Members_List, и поместить его в ADMIN_API_PMID_PROGRAM_CODE_HOLDING_TABLE с помощью Program_Code, MemberID и DBID.

В основной таблице всего около 150 записей, и строки, разделенные запятыми, могут иметь 5 значений.Я восприимчив к другим решениям.

Заранее спасибо

Ответы [ 2 ]

1 голос
/ 31 мая 2019

Я не проверял это, но, как я уже упоминал в комментариях, использование CURSOR - плохая идея; они по своей сути медленные, поскольку SQL Server выделяется при методах, основанных на множестве, а не итерационных задачах (а CURSOR является последним).

Я подозреваю , что это дает ответ, который вы ищете, и избегает CURSOR всего вместе:

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;
1 голос
/ 31 мая 2019

Причина бесконечного цикла может заключаться в том, что у вас нет «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
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...