【问题标题】:Time out error using cursor over 100k records使用超过 100k 记录的游标超时错误
【发布时间】:2014-08-20 07:15:47
【问题描述】:

我使用以下代码计算帐单,但是当我的记录变成 100k 时,我的应用返回超时错误,请告诉我如何重写它以提高性能???

注意: 我有借记和贷记记录,我的结果是 BALANCE 和 STATUS 。

declare @lbalance decimal=0 , @credit decimal=0 , @debit decimal=0 , @new_balance decimal=0,@balance decimal=0
DECLARE q1_cursor CURSOR DYNAMIC  for select debit,credit,balance,[status] from #t1
open q1_cursor 
fetch next from q1_cursor into @debit,@credit,@lbalance,@st


while @@fetch_status=0
begin

    set @new_balance=@new_balance+isnull(@credit,0)-isnull(@debit,0)
    if(@new_balance>1)
    begin
    set @st='creditor'
    set @balance=@new_balance
    end
    else
    begin
    set @st='debtor'
    set @balance=@new_balance*-1
    end

    update  #t1 set balance=@balance,[status]=@st where current of q1_cursor


    fetch next from q1_cursor into @debit,@credit,@lbalance,@st
end
close q1_cursor
deallocate q1_cursor

select * from #t1

编辑:

我像下面这样重写你的代码,但是,我得到了错误! “递归查询“HierarchicalCTE”的“余额”列中的锚点和递归部分之间的类型不匹配。”我该怎么办??

with HierarchicalCTE (ID,Date, Debit, Credit, Balance, [Status]) As
(
    select ID,Date, Debit, Credit, Balance, [Status]
        from #t1 
        where ID = 1
    union all
    select tbl.ID,tbl.Date, tbl.Debit, tbl.Credit
            , Balance=(case when ((tbl.Debit > 0 and cte.[Status] = 'debtor') or (tbl.Credit > 0 and cte.[Status] = 'creditor')) then abs(cte.Balance + tbl.Debit)
                when tbl.Debit > 0 and cte.[Status] = 'creditor' then abs(cte.Balance - tbl.Debit)
                else abs(cte.Balance - tbl.Credit)
                end) 
            , cast(case when ((tbl.Debit > 0 and cte.[Status] = 'debtor') or (tbl.Debit > 0 and tbl.Debit > cte.Balance)) then 'debtor'
                else 'creditor'
                end as char(20)) as [Status]
        from #t1 tbl
            inner join HierarchicalCTE cte
            on tbl.ID = cte.ID+1 

)

select * from HierarchicalCTE

【问题讨论】:

  • 我认为您根本不需要光标。能否提供一些数据和预期结果?
  • @deterministicFail 我已经在帖子中添加了一些信息,请检查一下
  • 游标无法处理 10 万条记录,而不是游标使用表值函数。
  • @Dineshalla 在帮助我解决这个问题之前没有使用任何表值函数

标签: sql-server-2008 query-performance accounting sqlperformance


【解决方案1】:

假设您的起始行有debit = 200, credit = 0, balance = 200, status = debtor,并且您希望将值输入到其余行的余额和状态中。

基于假设使用公用表表达式 (CTE) 的示例,并且表中有一个 ID 列..

declare @tbl table (id int, debit money, credit money, balance money, [status] varchar(20))

insert into @tbl (id, debit, credit, balance, [status])
values (1, 200, 0, 200, 'debtor')
, (2, 0, 300, 0, '')
, (3, 50, 0, 0, '')
, (4, 100, 0, 0, '')


; with cte (id, debit, credit, balance, [status])
as
(
    select id, debit, credit, balance, [status]
        from @tbl
        where id = 1
    union all
    select tbl.id, tbl.debit, tbl.credit
            , case when ((tbl.debit > 0 and cte.[status] = 'debtor') or (tbl.credit > 0 and cte.[status] = 'creditor')) then abs(cte.balance + tbl.debit)
                when tbl.debit > 0 and cte.[status] = 'creditor' then abs(cte.balance - tbl.debit)
                else abs(cte.balance - tbl.credit)
                end as balance
            , cast(case when ((tbl.debit > 0 and cte.[status] = 'debtor') or (tbl.debit > 0 and tbl.debit > cte.balance)) then 'debtor'
                else 'creditor'
                end as varchar(20)) as [status]
        from @tbl tbl
            inner join cte cte
            on tbl.id = cte.id + 1

)

select * from cte

初始数据..

id debit credit balance status 1 200.00 0.00 200.00 debtor 2 0.00 300.00 0.00 3 50.00 0.00 0.00 4 100.00 0.00 0.00

结果..

id debit credit balance status 1 200.00 0.00 200.00 debtor 2 0.00 300.00 100.00 creditor 3 50.00 0.00 50.00 creditor 4 100.00 0.00 50.00 debtor

【讨论】:

  • 我在这段代码中遇到错误“递归查询“HierarchicalCTE”的“余额”列中的锚点和递归部分之间的类型不匹配。”
  • 根据错误信息,您可能需要将 Balance 列的锚点强制转换为相同的数据类型。例如CAST(200 as money) as Balance 用于锚点。请出示您的 CTE 代码。
  • Cast (200 as money) 不起作用,仍然是同样的错误,但是当输入此代码 Balance=0 时,它可以工作,但它没有给我想要的结果!!!跨度>
猜你喜欢
  • 2022-01-16
  • 2023-03-06
  • 2017-03-25
  • 1970-01-01
  • 2017-07-02
  • 1970-01-01
  • 2021-12-31
  • 1970-01-01
  • 2018-07-10
相关资源
最近更新 更多