Как заменить Курсор решением на основе набора в MS SQL Server? - PullRequest
0 голосов
/ 30 января 2020

У меня был курсор в моей хранимой процедуре. Я обновил, пока l oop, чтобы выполнить быстрее. Но мои циклы пока занимают много времени. Пожалуйста, помогите мне отладить мой сценарий. Пожалуйста, найдите мой код ниже, с которого я удалил курсор и обновил, пока l oop. Я сделал сравнение продукции, которая дает то же самое. Но здесь занимает больше времени по сравнению с курсором.

DECLARE @orderArray INT
    ,@LeftTSMKEY NVARCHAR(250)
    ,@ListElid NVARCHAR(250)
    ,@ListType NVARCHAR(250)
    ,@ListType_Prev NVARCHAR(250)
    ,@inc INT

SET @ListType_Prev = ''
SET @inc = 0

DECLARE @cnt INT
DECLARE @t_cnt INT
DECLARE @Modules TABLE (
    ID INT IDENTITY(1, 1)
    ,ListElid VARCHAR(4000)
    ,ListType VARCHAR(30)
    ,orderArray VARCHAR(4000)
    ,LeftTSMKEY VARCHAR(30)
    )

INSERT INTO @Modules (
    ListElid
    ,ListType
    ,orderArray
    ,LeftTSMKEY
    )
SELECT ListElid
    ,ListType
    ,orderArray
    ,LeftTSMKEY
FROM QAT_ListElid
ORDER BY ListType
    ,orderArray

SET @cnt = 1

SELECT @t_cnt = count(*)
FROM @Modules

PRINT @t_cnt
PRINT 'loop started  in ' + cast(getdate() AS NVARCHAR(30))

WHILE @cnt <= @t_cnt
BEGIN
    SELECT @ListElid = ListElid
        ,@ListType = ListType
        ,@orderArray = orderArray
        ,@LeftTSMKEY = LeftTSMKEY
    FROM @Modules
    WHERE ID = @cnt

    IF @ListType <> @ListType_Prev
    BEGIN
        SET @inc = 0
        SET @ListType_Prev = @ListType
    END
    ELSE IF @ListType = @ListType_Prev
    BEGIN
        SET @inc = @inc + 1
    END

    IF @inc <> @orderArray
    BEGIN
        INSERT [QAT_ListElid2] (
            [ListElid]
            ,[ListType]
            ,[orderArray]
            ,[LeftTSMKEY]
            )
        VALUES (
            @ListElid
            ,@ListType
            ,@inc
            ,@LeftTSMKEY + CAST(@inc AS NVARCHAR(10)) + ']'
            )
    END

    SET @cnt = @cnt + 1
END

1 Ответ

2 голосов
/ 30 января 2020

Вы не предоставили набор данных и набор результатов для проверки, но, как почти всегда, курсор нужен редко. Вместо этого вы можете использовать запросы для достижения того же результата.

Я не знаю, сработает ли это, но следующее близко соответствует тому, что вы написали:

DECLARE @Modules TABLE (
    ID INT IDENTITY(1, 1)
    ,ListElid VARCHAR(4000)
    ,ListType VARCHAR(30)
    ,orderArray VARCHAR(4000)
    ,LeftTSMKEY VARCHAR(30)
    ,OrderedList INT
    )

INSERT INTO @Modules (
    ListElid
    ,ListType
    ,orderArray
    ,LeftTSMKEY
    ,OrderedList
    )
SELECT ListElid
    ,ListType
    ,orderArray
    ,LeftTSMKEY
    ,ROW_NUMBER() OVER (partition by ListType order by ListType,orderArray) - 1 as OrderedList
FROM QAT_ListElid

I ведите временную таблицу, но добавьте одно поле OrderedList , чтобы сохранить переменную @ в c на уровне строк. это простой счетчик, который начинается с 0 и переинициализируется каждый раз при изменении ListType.

INSERT [QAT_ListElid2] (
    [ListElid]
    ,[ListType]
    ,[orderArray]
    ,[LeftTSMKEY]
    )
SELECT ListElid
    ,ListType
    ,orderArray
    ,LeftTSMKEY + CAST(OrderedList AS NVARCHAR(10)) + ']'
FROM @Modules
WHERE OrderedList <> orderArray

Затем достаточно просто вставить в таблицу результатов QAT_ListElid2 все значения, но только если наши расчетные значения отличаются от orderArray .

Я считаю, что это то, чего вы хотите достичь. Если не совсем, вы можете адаптироваться к вашим требованиям. Суть в том, чтобы доказать, что вы можете жить без курсоров и повысить производительность.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...