如何优化游标到基于集合的运算符查询?

时间:2020-02-03 06:56:50

标签: sql sql-server optimization cursor set-operations

我的存储过程中有光标。我已更新为while循环以更快地执行。但是我的while循环需要同样长的时间。请帮助我调试脚本。请找到我下面的代码。

我需要更新游标以在MS SQL中设置基于操作符查询的帮助。

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

SET @ListType_Prev = ''
SET @inc = 0

DECLARE cursql CURSOR
FOR
SELECT ListElid
    ,ListType
    ,orderArray
    ,LeftTSMKEY
FROM QAT_ListElid
ORDER BY ListType
    ,orderArray

OPEN cursql

FETCH NEXT
FROM cursql
INTO @ListElid
    ,@ListType
    ,@orderArray
    ,@LeftTSMKEY

WHILE (@@Fetch_status = 0)
BEGIN
    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

    FETCH NEXT
    FROM cursql
    INTO @ListElid
        ,@ListType
        ,@orderArray
        ,@LeftTSMKEY
END

CLOSE cursql

DEALLOCATE cursql

请在下面找到示例数据

enter image description here

ListElid    ListType    orderArray  LeftTSMKEY
1000:odl5:7pt_ToxAcuDo[0]   1000:odl5:7pt_ToxAcuDo  0   ToxAcuDo[
106i:odl5:7pt_ToxAcuDo[0]   106i:odl5:7pt_ToxAcuDo  0   ToxAcuDo[
107:107:7pt_NIL[0]  107:107:7pt_NIL 0   NIL[
107:1827:7pt_NIL[0] 107:1827:7pt_NIL    0   NIL[
107:1827:7pt_NIL[1] 107:1827:7pt_NIL    1   NIL[
107:1827:7pt_NIL[3] 107:1827:7pt_NIL    3   NIL[
107:1hqn:7pt_NIL[0] 107:1hqn:7pt_NIL    0   NIL[
107:1hqn:7pt_NIL[1] 107:1hqn:7pt_NIL    1   NIL[
107:1rj7:7pt_NIL[0] 107:1rj7:7pt_NIL    0   NIL[
107:1rj7:7pt_NIL[1] 107:1rj7:7pt_NIL    1   NIL[
107:1rsg:7pt_NIL[0] 107:1rsg:7pt_NIL    0   NIL[
107:1s2r:7pt_NIL[0] 107:1s2r:7pt_NIL    0   NIL[
107:1s2r:7pt_NIL[1] 107:1s2r:7pt_NIL    1   NIL[
107:1s2r:7pt_NIL[2] 107:1s2r:7pt_NIL    2   NIL[
107:1s2r:7pt_NIL[4] 107:1s2r:7pt_NIL    4   NIL[
107:1vf:7pt_ NIL[0] 107:1vf:7pt_NIL    0    NIL[

2 个答案:

答案 0 :(得分:1)

如果我正确理解了这个问题,那么下一个陈述是可能的解决方案。

表格:

CREATE TABLE QAT_ListElid (
    ListElid nvarchar(250),  
    ListType nvarchar(250), 
    orderArray int, 
    LeftTSMKEY nvarchar(250)
)
INSERT INTO QAT_ListElid
    (ListElid, ListType, orderArray, LeftTSMKEY)
VALUES
    ('1000:odl5:7pt_ToxAcuDo[0]',   '1000:odl5:7pt_ToxAcuDo',   0, 'ToxAcuDo['),
    ('106i:odl5:7pt_ToxAcuDo[0]',   '106i:odl5:7pt_ToxAcuDo',   0, 'ToxAcuDo['),
    ('107:107:7pt_NIL[0]',          '107:107:7pt_NIL',          0, 'NIL['),
    ('107:1827:7pt_NIL[0]',         '107:1827:7pt_NIL',         0, 'NIL['),         -- 107:1827:7pt_NIL
    ('107:1827:7pt_NIL[1]',         '107:1827:7pt_NIL',         1, 'NIL['),         -- 107:1827:7pt_NIL
    ('107:1827:7pt_NIL[3]',         '107:1827:7pt_NIL',         3, 'NIL['),         -- 107:1827:7pt_NIL
    ('107:1hqn:7pt_NIL[0]',         '107:1hqn:7pt_NIL',         0, 'NIL['),
    ('107:1hqn:7pt_NIL[1]',         '107:1hqn:7pt_NIL',         1, 'NIL['),
    ('107:1rj7:7pt_NIL[0]',         '107:1rj7:7pt_NIL',         0, 'NIL['),
    ('107:1rj7:7pt_NIL[1]',         '107:1rj7:7pt_NIL',         1, 'NIL['),
    ('107:1rsg:7pt_NIL[0]',         '107:1rsg:7pt_NIL',         0, 'NIL['),
    ('107:1s2r:7pt_NIL[0]',         '107:1s2r:7pt_NIL',         0, 'NIL['),         -- 107:1s2r:7pt_NIL
    ('107:1s2r:7pt_NIL[1]',         '107:1s2r:7pt_NIL',         1, 'NIL['),         -- 107:1s2r:7pt_NIL
    ('107:1s2r:7pt_NIL[2]',         '107:1s2r:7pt_NIL',         2, 'NIL['),         -- 107:1s2r:7pt_NIL
    ('107:1s2r:7pt_NIL[4]',         '107:1s2r:7pt_NIL',         4, 'NIL['),         -- 107:1s2r:7pt_NIL
    ('107:1vf:7pt_ NIL[0]',         '107:1vf:7pt_NIL',          0, 'NIL[')
CREATE TABLE QAT_ListElid2 (
    ListElid nvarchar(250),  
    ListType nvarchar(250), 
    orderArray int, 
    LeftTSMKEY nvarchar(250)
)

声明:

;WITH ChangesCTE AS (
    SELECT 
        ListElid, ListType, orderArray, LeftTSMKEY,
        CASE 
            WHEN ListType = LAG(ListType) OVER (PARTITION BY ListType ORDER BY orderArray) THEN 1 
            ELSE 0
        END AS [Change]
    FROM QAT_ListElid
), FinalCTE AS (
    SELECT 
        ListElid, ListType, orderArray, LeftTSMKEY,
        SUM([Change]) OVER (PARTITION BY ListType ORDER BY ListType, orderArray) AS [inc]
    FROM ChangesCTE
)
INSERT INTO QAT_ListElid2
    ([ListElid], [ListType], [orderArray], [LeftTSMKEY])
SELECT 
    ListElid, 
    ListType, 
    [inc] AS orderArray, 
    LeftTSMKEY + CAST([inc] as nvarchar(10)) + ']' AS LeftTSMKEY
FROM FinalCTE
WHERE orderArray <> [inc]

或anotehr语句作为第二个选择:

INSERT INTO QAT_ListElid2
    ([ListElid], [ListType], [orderArray], [LeftTSMKEY])
SELECT 
    ListElid, 
    ListType, 
    [inc] AS orderArray, 
    LeftTSMKEY + CAST([inc] as nvarchar(10)) + ']' AS LeftTSMKEY
FROM (
    SELECT 
        ListElid, ListType, orderArray, LeftTSMKEY,
        ROW_NUMBER() OVER (PARTITION BY ListType ORDER BY orderArray) - 1 AS [Inc]
    FROM QAT_ListElid
) t
WHERE orderArray <> [inc]

结果(插入的两行):

--------------------------------------------------------------
ListElid            ListType            orderArray  LeftTSMKEY
--------------------------------------------------------------
107:1827:7pt_NIL[3] 107:1827:7pt_NIL    2           NIL[2]
107:1s2r:7pt_NIL[4] 107:1s2r:7pt_NIL    3           NIL[3]

答案 1 :(得分:0)

它们基于DECLARE CURSOR语法,主要用于Transact-SQL脚本,存储过程和触发器。 Transact-SQL游标在服务器上实现,并由从客户端发送到服务器的Transact-SQL语句管理。它们也可能包含在批处理,存储过程或触发器中。

类似于INTVARCHAR和其他数据类型,游标在T-SQL批处理中声明。 SQL Server附带了相关的说明来对其进行管理:

  1. OPEN告诉SQL Server运行查询并使用结果集填充游标;

  2. CLOSE通知SQL Server释放游标使用的资源;

  3. FETCH通知SQL Server从游标中检索特定行。使用此函数时,可以在@@ FETCH_STATUS变量中获取FETCH指令的结果。如果将其设置为0,则表示指令已成功。