用普通T SQL語句代替游標操作

2022-02-15 00:07:17 字數 2118 閱讀 2970

經常寫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

kouter

(

select

isnull(sum(amount), 0) as balance from ref where sort <=

k.sort

)twhere

@amount

> t.balance -

k.amount

--這裡, t表累加了到k表當前記錄為止的應付總額,

--可支付的訂單應滿足的條件是: 付款單金額@amount > 我前面乙個訂單為止的總額( 即 balance - amount)

3. 開始向關係表插入記錄

insert

into

t_relation(pay_id, order_id, amount)

select

@pay_id

,id,

payfrom

@orders;

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

update t set t.paid = t.paid +

k.pay

from

@orders

kinner

join t_orders t on t.id = k.id

大功告成, 看起來好像有很多語句, 仔細數一下, 其實完成"關係鏈結"的只有三條語句.

用迴圈代替游標

在sql的sp開發中,游標有不可或缺的作用。但是,一些不當的使用游標,會造成嚴重系統效能的下降,所有呢,很多的人就想找乙個方法,即能達到游標的功能,又對效能影響小一些。這就是本文要講的用迴圈代替游標。一般情況下,用光標的目的就是要達到乙個迴圈,可是我們要是以迴圈來作呢,如何來控制當前的變數值就是關鍵...

建議104 用多型代替條件語句

假設開發自動駕駛系統。在設計之初,自動駕駛系統擁有乙個駕駛系統命令的列舉型別 enum drivecommand start,stop 又假設有乙個駕駛的方法處理車輛接收到的指令。一開始我們這樣編碼 static void main string args drivecommand comand d...

T SQL 語句(六) 觸發器操作

一 觸發器簡介 1 觸發器的功能 a 實現比約束更為複雜的資料約束 b 可以檢查 sql 所做的操作是否被允許 c 修改其他資料庫裡表的資料 d 可以一次呼叫多個儲存過程 e 傳送sql mail f 返回自定義錯誤資訊 g 修改原來要操作的 sql 語句 h 防止資料表結構更改或表被刪除 2 觸發...