在編寫SQL批處理或存儲(chǔ)過程代碼的過程中,經(jīng)常會(huì)碰到有些業(yè)務(wù)邏輯的處理,需要對(duì)滿足條件的數(shù)據(jù)記錄逐行進(jìn)行處理,這個(gè)時(shí)候,大家首先想到的方案大部分是用“游標(biāo)”進(jìn)行處理。
舉個(gè)例子,在訂單管理系統(tǒng)中,客服需要對(duì)訂單日期為2012-09-01的銷售訂單進(jìn)行某個(gè)批量操作,比如批量發(fā)貨操作,后臺(tái)業(yè)務(wù)邏輯處理時(shí),需要對(duì)滿足條件的訂單記錄進(jìn)行逐行處理。
我首先是采用“游標(biāo)”編寫的業(yè)務(wù)邏輯存儲(chǔ)過程,SQL代碼可以如下:
游標(biāo)
1
DECLARE
@ORDERID
VARCHAR
(
30
)
2
3
--
聲明局部游標(biāo):從訂單數(shù)據(jù)表獲取訂單日期為2012-09-01,訂單類型為Sales的訂單編號(hào)
4
DECLARE
CURSOR_ORDER
CURSOR
LOCAL
FOR
5
SELECT
ORDERID
FROM
ORDERHD H
WHERE
ORDERDATE
=
'
2012-09-01
'
AND
H.ORDERTYPE
=
'
Sales
'
6
7
--
打開游標(biāo)
8
OPEN
CURSOR_ORDER
9
FETCH
NEXT
FROM
CURSOR_ORDER
INTO
@ORDERID
10
WHILE
@@FETCH_STATUS
=
0
11
BEGIN
12
13
/*
14
此處編寫對(duì)當(dāng)前行數(shù)據(jù)的業(yè)務(wù)邏輯處理代碼
15
*/
16
17
--
得到下一條記錄
18
FETCH
NEXT
FROM
CURSOR_ORDER
INTO
@ORDERID
19
END
20
21
--
關(guān)閉游標(biāo)
22
CLOSE
CURSOR_ORDER
23
--
釋放游標(biāo)
24
DEALLOCATE
CURSOR_ORDER
?
? 功能是實(shí)現(xiàn)了,但是客服在實(shí)際使用過程中,經(jīng)常反饋批量操作效率太慢,需要等待較長時(shí)間才能完成操作。經(jīng)過測(cè)試發(fā)現(xiàn),速度慢在游標(biāo)逐行處理過程中,當(dāng)需要處理的記錄數(shù)較大,而且游標(biāo)處理位于數(shù)據(jù)庫事務(wù)內(nèi)時(shí),速度非常慢。
那么,有什么方法可以解決這個(gè)處理速度慢的問題嗎?
經(jīng)不斷的嘗試,終于找到一個(gè)方法,那就是用 WHILE循環(huán) 來進(jìn)行逐行數(shù)據(jù)處理。首先將需要處理的數(shù)據(jù)記錄獲取到一個(gè)臨時(shí)表(此臨時(shí)表包括2個(gè)重要字段:REFID - 記錄行號(hào),DealFlg:行處理標(biāo)識(shí),用1/0標(biāo)識(shí)行是否已處理),然后WHILE循環(huán)對(duì)臨時(shí)表進(jìn)行逐行處理,SQL代碼如下:
While 循環(huán)
1
DECLARE
@REFID
INT
2
,
@ORDERID
VARCHAR
(
30
)
3
4
--
獲取待處理的數(shù)據(jù)記錄到臨時(shí)表
5
--
字段說明:REFID:記錄行號(hào) / DealFlg:行處理標(biāo)識(shí)
6
SELECT
REFID
=
IDENTITY
(
INT
,
1
,
1
), DealFlg
=
0
, ORDERID
7
INTO
#Temp_Lists
8
FROM
ORDERHD
9
WHERE
ORDERDATE
=
'
2012-09-01
'
AND
H.ORDERTYPE
=
'
Sales
'
10
11
--
獲取臨時(shí)表數(shù)據(jù)的最小行號(hào)
12
SELECT
@REFID
=
MIN
(REFID)
FROM
#Temp_Lists
WHERE
DealFlg
=
0
13
14
--
若最小行號(hào)不為空(有需要處理的數(shù)據(jù))
15
WHILE
@REFID
IS
NOT
NULL
16
BEGIN
17
18
--
獲取當(dāng)前處理行的信息
19
SELECT
@ORDERID
=
ORDERID
FROM
#Temp_Lists
WHERE
REFID
=
@REFID
20
21
/*
22
此處編寫對(duì)當(dāng)前行數(shù)據(jù)的業(yè)務(wù)邏輯處理代碼
23
*/
24
25
--
標(biāo)識(shí)當(dāng)前行已處理完畢
26
UPDATE
#Temp_Lists
SET
DealFlg
=
1
WHERE
REFID
=
@REFID
27
28
--
選擇下一行號(hào)
29
SELECT
@REFID
=
MIN
(REFID)
FROM
#Temp_Lists
WHERE
DealFlg
=
0
AND
REFID
>
@REFID
30
31
END
? 經(jīng)過這樣對(duì)原存儲(chǔ)過程進(jìn)行修正后,批量操作速度得到顯著提升。
有興趣的朋友,可以嘗試使用這個(gè)方法替代游標(biāo),對(duì)比2種方案的處理效率。
?
更多文章、技術(shù)交流、商務(wù)合作、聯(lián)系博主
微信掃碼或搜索:z360901061
微信掃一掃加我為好友
QQ號(hào)聯(lián)系: 360901061
您的支持是博主寫作最大的動(dòng)力,如果您喜歡我的文章,感覺我的文章對(duì)您有幫助,請(qǐng)用微信掃描下面二維碼支持博主2元、5元、10元、20元等您想捐的金額吧,狠狠點(diǎn)擊下面給點(diǎn)支持吧,站長非常感激您!手機(jī)微信長按不能支付解決辦法:請(qǐng)將微信支付二維碼保存到相冊(cè),切換到微信,然后點(diǎn)擊微信右上角掃一掃功能,選擇支付二維碼完成支付。
【本文對(duì)您有幫助就好】元

