在銀行金融系統中,我們常常都要實現銀行轉賬這樣的業務操作,而這種金融系統併發性相當高,需要考慮的如何提高性能和保證安全性等相關的問題。使用存儲過程來實現銀行轉賬是一個很好的選擇。
SQL SERVER數據庫中的存儲過程相對於應用程序中來操作Transact-SQL語言的優缺點:
優點:
1. 存儲過程已在服務器註冊,預編譯,存儲過程預先編譯好放在數據庫內,減少編譯語句所花的時間
2. 存儲過程可以用於減少網絡通信流量,存儲過程代碼直接存儲於數據庫中,執行的時候只需要應用程序傳遞參數即可,而不需要整段的T-SQL代碼傳遞到數據庫中。
3. 重用性高,一段存儲過程,可以在應用程序中不同的位置來調用。
4. 可維護性高,把整個業務的操作封裝在一起,有利於以後做代碼的替換操作,而應用程序會在日後不斷的維護中,會導致TrancSQL過程代碼會變得越來越複雜,同時,更新存儲過程通常比更新應用程序簡單的多,更新應該程序需要編譯,部署。
5. 使用緩存改善性能,編譯好的存儲過程直接進入SQL SERVER的緩存中,使得下次執行的時候,能馬上調用。而在SQL SERVER 2005中,執行計劃已針對所有 T-SQL 批處理進行了緩存,效率和存儲過程差不多了。
6. 強制使用數據庫中的安全認證機制,使得應用程序的安全性提高:
a) 對存儲過程向特定用戶授權,也可以提供對特定數據的訪問。
b) 增強代碼安全,通過傳遞參數的方式,能有效防止 SQL注入。
缺點:
1. 可移植性差
a) 由於存儲過程將應用程序綁定到 SQL Server,因此使用存儲過程封裝業務邏輯將限制應用程序的可移植性。
b) 如果應用程序的可移植性在您的環境中非常重要,則將業務邏輯封裝在不特定於 RDBMS 的中間層中可能是一個更佳的選擇。
2. 增加數據庫服務器的負載
3. 舊版本的SQL SERVER的編程SQL語句功能較差,SQL SERVER 2005有所改善
4. 調試過程不如應用程序方便
下面我們來看看如何來使用SQL SERVER 2005的存儲過程實現銀行轉賬這樣的業務操作:
1. 準備工作:先創建一個account銀行賬戶表,腳本如下:
create table account(
id int identity(1,1) primary key,
cardno char(20),
money numeric(18,2)
)
insert into account values('01',1000.0)
insert into account values('02',1000.0)
2. 實現方案1:
不考慮任何的條件,簡單實現兩個賬戶之間的轉賬操作。
參數:
@out_cardno:轉出賬戶
@in_cardno: 轉入賬戶
@money: 轉賬金額
CREATE PROCEDURE sp_transfer_money1
@out_cardno char(20),
@in_cardno char(20),
@money numeric(18,2)
AS
BEGIN
update account set money = money-@money where cardno=@out_cardno
update account set money = money+@money where cardno=@in_cardno
PRINT '轉賬成功.'
END
-- 執行上面的存儲過程
EXEC sp_transfer_money1 '01','02',1200.0
出現問題:
轉出賬戶”01”的只有1000塊,但是卻能夠成功的轉1200塊,這樣的做法是不可思議的。
3. 實現方案2:
加入對轉出賬戶的餘額判斷:
CREATE PROCEDURE sp_transfer_money2
@out_cardno char(20),
@in_cardno char(20),
@money numeric(18,2)
AS
BEGIN
DECLARE @remain numeric(18,2)
select @remain=money from account where cardno=@out_cardno
IF @remain>=@money
BEGIN
update account set money = money-@money where cardno=@out_cardno
update account set money = money+@money where cardno=@in_cardno
PRINT '轉賬成功.'
END
ELSE
BEGIN
PRINT '餘額不足.'
END
END
EXEC sp_transfer_money2 '01','02',1000.0
出現問題:
1. 存儲過程的參數從外部出入,但是不能確定參數的合法性,一旦參數出現問題,執行存儲過程就可能發生錯誤,導致部分業務代碼執行不成功,發生數據不一致的問題。
2. 缺少事務控制的管理
4. 實現方案3:
CREATE PROCEDURE sp_transfer_money3
@out_cardno char(20),
@in_cardno char(20),
@money numeric(18,2)
as
BEGIN
DECLARE @remain numeric(18,2)
select @remain=money from account where cardno=@out_cardno
if @remain>@money
BEGIN
BEGIN TRANSACTION T1
update account set money = money-@money where cardno=@out_cardno
update account set money = money+@money where cardno=@in_cardno PRINT '轉賬成功.'
if @remain>@money
begin
rollback transaction
end
COMMIT TRANSACTION T1
END
ELSE
BEGIN
PRINT '餘額不足.'
END
END
EXEC sp_transfer_money3 '01','02',100.0
現實生活中的金融業務是相當複雜的,上面的幾個方案只是模擬了最基本的情況,譬如,跨行之間的轉賬,同行不同區的轉賬這些都是具體的業務需求。要把這些業務都使用存儲過程來實現的話,對我們的數據庫開發人員來說,要求就更高了。