如何在sql中增加游标性能

时间:2015-12-23 09:52:55

标签: sql-server

我使用触发器重新计算多个数据。 在触发器中我使用了cursor.in cursor我已经使用了另外一个包含1个光标的sp。

因此,仅计算80行数据的速度非常慢。计算数据需要20秒。所以请快速给我任何建议或解决方案。

感谢

这是我的触发器

/****** Object:  Trigger [dbo].[tr_TransactionJournal_InsteadOfDelete]    Script Date: 12/23/2015 3:13:09 PM ******/
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
ALTER TRIGGER [dbo].[tr_TransactionJournal_InsteadOfDelete]
    ON [dbo].[TransactionJournal]
    INSTEAD OF DELETE
AS
    SET NOCOUNT ON;

DECLARE
    @TxNum INT,
    @TxDate DATE

/*
    declare @TempDetailTable to figure out which ChartAcctCode & Item needs to be recalculated
*/
DECLARE @TempDetailTable TABLE (
    ChartAcctCode NVARCHAR(10),
    ItemCode NVARCHAR(10)
)

DECLARE @MyCursor_1 CURSOR
SET @MyCursor_1 = CURSOR FAST_FORWARD
FOR
    SELECT TxNum,TxDate FROM DELETED

OPEN @MyCursor_1
FETCH NEXT FROM @MyCursor_1
INTO @TxNum,@TxDate

WHILE @@fetch_status = 0 -- This is executed as long as the previous fetch succeeds.
BEGIN
------------------  

    BEGIN TRANSACTION
    INSERT INTO @TempDetailTable
    SELECT DISTINCT tjd.ChartAcctCode, tjd.ItemCode
    FROM dbo.TransactionJournalDetail AS tjd 
    WHERE (tjd.TxNum = @TxNum)-- AND    tjd.ItemCode IS NOT NULL
    COMMIT TRANSACTION

    /*
    Actually deleting FROM TxJournal & TxJournalDetail
    */
    DELETE FROM TransactionJournal WHERE TxNum=@TxNum

    /*
    Start Recalculating...
    */
    DECLARE @MyChartAcctCode NVARCHAR(10)
    DECLARE @MyItemCode NVARCHAR(10)

    DECLARE @MyCursor CURSOR
    /*
    1st Loop to RecalcQAV if Detail has any ChartAcctCode = "AINV"
    */
    SET @MyCursor = CURSOR FAST_FORWARD
    FOR
        SELECT ItemCode FROM @TempDetailTable WHERE ChartAcctCode = 'INV'

    OPEN @MyCursor
    FETCH NEXT FROM @MyCursor
    INTO @MyItemCode

    WHILE @@fetch_status = 0
    BEGIN

        EXEC RecalcQAV @MyItemCode, @TxDate;

    FETCH NEXT FROM @MyCursor
    INTO @MyItemCode

    END
    /*
    2nd Loop to RecalcAcctBalance if Detail has any ChartAcctCode = "AINV"
    */

    SET @MyCursor = CURSOR FAST_FORWARD
    FOR
        SELECT ChartAcctCode FROM @TempDetailTable

    OPEN @MyCursor
    FETCH NEXT FROM @MyCursor
    INTO @MyChartAcctCode

    WHILE @@fetch_status = 0
    BEGIN

        EXEC RecalcAcctBalance @MyChartAcctCode, @TxDate;

    FETCH NEXT FROM @MyCursor
    INTO @MyChartAcctCode

    END

    CLOSE @MyCursor;
    DEALLOCATE @MyCursor;

------------------
FETCH NEXT FROM @MyCursor_1
INTO @TxNum,@TxDate
END

CLOSE @MyCursor_1;
DEALLOCATE @MyCursor_1;

1 个答案:

答案 0 :(得分:0)

ALTER PROCEDURE [dbo].[RecalcAcctBalance]
(
    @ChartAcctCode NVARCHAR(10),
    @BeginDate DATE
)
AS BEGIN

    SET NOCOUNT ON;

    DECLARE @LastDate DATE
    SELECT @LastDate = MAX(tj.TxDate)
    FROM dbo.TransactionJournal AS tj
    JOIN dbo.TransactionJournalDetail AS tjd ON tj.TxNum = tjd.TxNum
    WHERE tj.TxDate < @BeginDate
        AND tjd.ChartAcctCode = @ChartAcctCode

    DECLARE @MyTable TABLE (
        AutoId INT IDENTITY(1,1) PRIMARY KEY,
        TxDate DATE,
        TxDetailId INT
    )
    INSERT INTO @MyTable (TxDate, TxDetailId)
    SELECT tj.TxDate, tjd.AutoId
    FROM dbo.TransactionJournal AS tj
    JOIN dbo.TransactionJournalDetail AS tjd ON tj.TxNum = tjd.TxNum
    WHERE tj.TxDate >= ISNULL(@LastDate, @BeginDate)
        AND tjd.ChartAcctCode = @ChartAcctCode
    ORDER BY tj.TxDate, tj.SourceDocOrder, tjd.AutoId

    DECLARE
        @LastDateMaxId INT, 
        @TxDetailId INT,
        @LChartAcctBalance MONEY = 0

    IF @LastDate IS NOT NULL
    BEGIN

        SELECT @TxDetailId = TxDetailId
        FROM (
            SELECT TxDetailId, RowNum = ROW_NUMBER() OVER (ORDER BY AutoId DESC)
            FROM @MyTable
            WHERE TxDate = @LastDate
        ) t
        WHERE t.RowNum = 1

        SELECT @LChartAcctBalance = ISNULL(ChartAcctBalance, 0)
        FROM dbo.TransactionJournalDetail
        WHERE AutoId = @TxDetailId

    END

    ;WITH cte AS 
    (
        SELECT *, val = @LChartAcctBalance + SUM(Amount) OVER (ORDER BY AutoId)
        FROM dbo.TransactionJournalDetail
        WHERE AutoId IN (
                SELECT TxDetailId
                FROM @MyTable
                WHERE TxDate >= @BeginDate
            )  
    )
    UPDATE cte
    SET ChartAcctBalance = val

END

第二个sp太大了,无法进行重构......无论如何主要问题 - 按项目处理的业务逻辑......