經常寫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. 開始向關係表插入記錄
insertinto
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 觸發...