zoukankan      html  css  js  c++  java
  • 用普通TSQL语句代替游标操作

    经常写SQL的同学们都知道, 在Sql Server的IDE中如果SQL嵌套的层次太多, 查看和修改代码将变得非常痛苦, 再加上游标用得不恰当很容易出现"锁"和"性能"问题.

    所以通常大大们都劝大家尽量少用游标, 阿飞个人很喜欢将业务逻辑写在存储过程里, 于是也经常遇到需要游标逻辑的地方, 这里就跟大家分享一点使用普通T-SQL语句代替游标的处理方案.

    业务需求:
    订单表 t_orders (id int, total money, paid money, date datetime)
    付款单 t_pays (id int, amount money, date datetime)
    付款单和订单关系表 t_relation (pay_id int, order_id int, amount money)

    财务付款时, 往 t_pays 插入一条记录, 并且需要按照订单表的时间顺序在 t_relation 表标记出此次付款用于支付了哪些订单, 一个付款单可能会对应多个订单, 一个订单也可能分几次支付, 所以 t_relation 表中存储的是多对多的关系.

    存储过程的输入参数 @amount money, 表示此次支付金额

    1. 首先插入 t_pays 记录, set @pay_id = SCOPE_IDENTITY(); 获取此次付款单编号

    2. 使用一个变量表来存储需要支付的订单

    --amount 表示此订单需要支付的金额, pay 表示此次将要支付的金额, sort 用来表示支付顺序
    declare @orders table(id int, amount money, pay money, sort int);  
    
    --使用CTE(Common Table Expressions)列出所有需要支付的订单
    with REF(id, amount, sort)
    as
    (
        select id, total - paid, Row_Number()over(order by date) from t_orders where total > paid
    ) --然后筛选出此次可以支付的订单, 插入到变量表
    --需要注意的是, 普通订单此次支付的金额是 total - paid, 但是最后一个订单, 付款单金额如果不足(@amount < balance)就应该是 @amount - (balance - amount)
    insert into @orders(id, amount, sort, pay)
    select K.id, K.amount, K.sort, case when @amount >= T.balance then K.amount else @amount - (T.balance - K.amount) end from REF as K
    outer apply
    (
        select  IsNull(sum(amount), 0) as balance from REF where sort <= K.sort
    )T
    where @amount > T.balance - K.amount
    --这里, T表累加了到K表当前记录为止的应付总额,
    --可支付的订单应满足的条件是: 付款单金额@amount > 我前面一个订单为止的总额( 即 balance - amount)

    3. 开始向关系表插入记录

    insert into t_relation(pay_id, order_id, amount)
    select
    @pay_id,
    id,
    pay
    from @orders;

    4. 更新t_orders 表的 已付金额(paid)

    update T set T.paid = T.paid + K.pay
    from @orders K
    inner join t_orders T on T.id = K.id

    大功告成, 看起来好像有很多语句, 仔细数一下, 其实完成"关系链接"的只有三条语句.




  • 相关阅读:
    如何优化数据库中数据的查询
    2句sql语句的比较
    未来五年程序员应当具备的十项技能
    中小IT企业如何留住80后技术人才
    ORACLE的sign函数和DECODE函数
    Windows Server 2008系统 安装Oracle 10g 错误
    ORACLE 错误 ora01830 解决方法
    oracle instr函数
    Oracle 9i安装时没有找到OCS4J.properties 解决办法
    C# 中的委托和事件
  • 原文地址:https://www.cnblogs.com/xiarugu/p/2660206.html
Copyright © 2011-2022 走看看