SQL Server循环记录

时间:2011-07-08 17:31:01

标签: sql sql-server-2005 ms-access vba loops

我一直在线寻找重写当前VBA / MS Access Sub以在SQL Server 2005中的存储过程中工作的最佳方法。除非我们能够完全解释,否则我们不应该使用CURSORS项目我们不能以任何其他方式做到这一点的原因。

当前代码:

Public Sub updcsh()

Dim tranamt
Dim Acct
Dim acct2
Dim Csh
Dim recSet As Recordset

    DAO.DBEngine.SetOption dbMaxLocksPerFile, 100000

    Set recSet = CurrentDb.OpenRecordset("FndVios")
    recSet.MoveFirst


    Do Until recSet.EOF
        Acct = recSet![ID]
        tranamt = recSet![TAM]

        If Acct <> acct2 Then
            Csh = recSet![Due]
        End If

        Csh = Csh+ tranamt
        acct2 = Acct

        recSet.Edit
            recSet![Due] = Csh
        recSet.Update

        recSet.MoveNext
    Loop
End Sub

正在打开的记录集如下:

SELECT ID, EXEC_TM, Due, TAM
FROM FRT
ORDER BY ID, EXEC_DT, EXEC_TM, D_C_CD, SEQ_NBR, TAM DESC

我搜索了SO并找到了this。我查看了游标和其他方法,如何为存储过程写这个,我无法弄清楚重写这个的正确方法。

任何人都可以提出任何建议吗?我应该使用临时表吗?我之前没有这样做,我很难理解如何继续。

编辑:

Sample Data
Original:

ID         EXEC_TM    Due        TAM
12345678   12343811   $9250.81   $-6561.91
12345678   12343822   $9250.81   $-4374.63
12345678   15581917   $9250.81   $-4762.76

Final Result:

ID         EXEC_TM    Due         TAM
12345678   12343811   $2688.87    $-6561.91
12345678   12343822   $-1685.76   $-4374.63
12345678   15581917   $-6448.52   $-4762.76

2 个答案:

答案 0 :(得分:7)

从流程重新设计的角度来看,汤姆的答案是更好的答案。下面的代码是以CURSOR形式重新编写您当前的逻辑。

我绝不认可这种方法,但这就是你要求的。您可能需要更正数据类型等才能使其正常工作。

DECLARE @ID int,
        @Exec_TM int,
        @Due money,
        @TAM money,
        @ID2 int = 0,
        @Cash money


DECLARE RecSet CURSOR FOR

SELECT ID, EXEC_TM, Due, TAM
FROM FRT
ORDER BY ID, EXEC_DT, EXEC_TM, D_C_CD, SEQ_NBR, TAM DESC

OPEN RecSet
FETCH NEXT FROM RecSet INTO @ID, @Exec_TM, @Due, @TAM

WHILE (@@FETCH_STATUS = 0)  
        BEGIN  

            IF @ID <> @ID2 SET @Cash = @Due

            SET @Cash = @Cash + @TAM

            SET @ID2 = @ID

            UPDATE FRT
            SET Due = @Cash
            WHERE ID = @ID
            AND EXEC_TM = @Exec_TM
            AND Due = @Due
            AND TAM = @TAM  

            FETCH NEXT FROM RecSet INTO @ID, @Exec_TM, @Due, @TAM

        END


CLOSE RecSet
DEALLOCATE RecSet

答案 1 :(得分:3)

首先,从数据库设计的角度(可能从会计角度来看)保持“到期”数量是一个可怕的想法。

其次,根据您的逻辑,如果某个帐户的第一行有交易金额,那么每次您运行此流程时,它将进一步甩掉您的到期金额,直到您开始欠客户的钱。

以下是基于集合的基本方法,用于计算运行总计:

SELECT
    L1.account_id,
    L1.transaction_date,
    L1.amt,
    SUM(L2.amt)
FROM
    Ledger L1
INNER JOIN Ledger L2 ON
    L2.account_id = L1.account_id AND
    L2.transaction_date <= L1.transaction_date
GROUP BY
    L1.account_id,
    L1.transaction_date,
    L1.amt

因为您将“到期”列分开,所以这会导致问题,因为看起来您只计算第一个条目。您可以在上面的查询中考虑到这一点,但它将涉及子查询或其他连接。