用普通T-SQL语句代替游标操作

经常写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

 

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




posted @   疯子阿飞  阅读(2196)  评论(1编辑  收藏  举报
编辑推荐:
· 如何编写易于单元测试的代码
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
阅读排行:
· 周边上新:园子的第一款马克杯温暖上架
· Open-Sora 2.0 重磅开源!
· 分享 3 个 .NET 开源的文件压缩处理库,助力快速实现文件压缩解压功能!
· Ollama——大语言模型本地部署的极速利器
· [AI/GPT/综述] AI Agent的设计模式综述
点击右上角即可分享
微信分享提示