在我前面很多篇關于框架設計和介紹的文章里面衬浑,大多數都是利用框架提供的基礎性API進行各種的操作换怖,包括增刪改查桦沉、分頁等各種實現(xiàn)和其衍生的實現(xiàn)役纹,而這些實現(xiàn)絕大多數是基于SQL的標準操作實現(xiàn)的偶摔,由于框架的底層是利用了微軟企業(yè)庫Enterprise Library,因此框架也是很好的支持存儲過程的各種調用促脉,不過由于整體性和數據庫遷移方面的考慮辰斋,建議一般使用標準的SQL操作而已,這樣能夠很大程度上保證數據庫可以很平滑過渡到其他數據庫瘸味,如Access宫仗、SQLite等單機版數據庫。但是旁仿,有時候我們提供對存儲過程的支持也是十分必要的藕夫,有些業(yè)務可能就只是固定在某種特定的數據庫上跑,如SQLServer枯冈、Oracle等這些支持存儲過程的關系型數據庫毅贮,有些業(yè)務可能還真的需要存儲過程的整體性的封裝;基于這個原因尘奏,我撰寫了這篇文章滩褥,力求從較為全面的角度上闡述存儲過程的編寫、實現(xiàn)和演化提煉方面做一個介紹炫加。
1瑰煎、SQLServer存儲過程的編寫
雖然存儲過程一般用于處理一些復雜的邏輯關系或者報表內容,不過為了介紹方便俗孝,我們從幾個較為基礎的操作進行介紹酒甸。
我們以一個客戶表來進行對應的存儲過程來介紹,先介紹客戶表T_Customer的表定義赋铝。
它的SQLServer腳本如下所示
create table dbo.T_Customer (
ID nvarchar(50) not null,
Name nvarchar(50) null,
Age int null,
Creator nvarchar(50) null,
CreateTime datetime null,
constraint PK_T_CUSTOMER primary key (ID)
)
為了介紹存儲過程的編寫烘挫,我們以這個表的相關操作的存儲過程來進行介紹,存儲過程一般可以分為下面幾種情況柬甥。
1)提供執(zhí)行處理饮六,可對執(zhí)行結果進行反饋
這種情況常常可以見到苛蒲,如可以對插入卤橄、更新、刪除等操作進行處理臂外,并獲得執(zhí)行的結果窟扑,下面是這兩種存儲過程的代碼喇颁。
------------------------------------
--作者:伍華聰 http://wuhuacong.cnblogs.com
--創(chuàng)建時間:2014年11月27日
--功能描述:插入數據到表中
------------------------------------
CREATE PROCEDURE dbo.T_Customer_Insert
(
@ID varchar(50),
@Name varchar(50) ,
@Age int
)
AS
begin tran
Insert into dbo.T_Customer( ID,Name,Age ) Values( @ID,@Name,@Age )
if @@error!=0
begin
rollback
end
else
begin
commit
end
go
------------------------------------
--作者:伍華聰 http://wuhuacong.cnblogs.com
--創(chuàng)建時間:2014年11月27日
--功能描述:以字段ID為關鍵字,修改表中的數據
------------------------------------
CREATE PROCEDURE dbo.T_Customer_UpdateByID
(
@ID varchar(50),
@Name varchar(50) ,
@Age int
)
AS
begin tran
Update dbo.T_Customer Set Name=@Name,Age=@Age Where ID= @ID
if @@error!=0
begin
rollback
end
else
begin
commit
end
go
------------------------------------
--作者:伍華聰 http://wuhuacong.cnblogs.com
--創(chuàng)建時間:2014年11月27日
--功能描述:以字段ID為關鍵字嚎货,刪除表的記錄
------------------------------------
CREATE PROCEDURE dbo.T_Customer_DeleteByID
(
@ID varchar(50)
)
AS
begin tran
Delete From dbo.T_Customer where ID=@ID
if @@error!=0
begin
rollback
end
else
begin
commit
end
go
2)提供執(zhí)行處理橘霎,獲得一個或者多個返回性參數,并可對執(zhí)行結果進行反饋殖属。
基于上面的處理方式姐叁,我們可能還有一種情況,就是需要執(zhí)行存儲過程個洗显,并返回對應的返回參數外潜,我們可以在程序里面利用代碼獲取這些返回參數的數值,從而用作其他用途挠唆。
因此处窥,這種操作,如要是獲取返回性參數的情況玄组,如下所示是判斷記錄是否存在滔驾,以及獲取客戶最大年齡的兩個存儲過程。
------------------------------------
--作者:伍華聰 http://wuhuacong.cnblogs.com
--創(chuàng)建時間:2014年11月27日
--功能描述:以字段ID為關鍵字俄讹,檢查表中是否存在符合條件的記錄
------------------------------------
CREATE PROCEDURE dbo.T_Customer_ExistByID
(
@Exist int output ,
@ID varchar(50)
)
AS
Select @Exist = Case When Exists (Select 1 From dbo.T_Customer Where ID=@ID) Then 1 Else 0 End
go
------------------------------------
--作者:伍華聰 http://wuhuacong.cnblogs.com
--創(chuàng)建時間:2014年11月27日
--功能描述:獲取客戶最大年齡
------------------------------------
CREATE PROCEDURE dbo.T_Customer_MaxAge
( @MaxAge int output )
AS
Select @MaxAge=Case When Max(Age) is NULL Then 0 Else Max(Age) End From dbo.T_Customer
go
3)提供查詢處理嵌灰,并返回實體對象
這小節(jié)后面介紹的內容,都是存儲過程的返回值颅悉,這些或者是一條記錄,或者是多條記錄的查詢結果迁匠,這個在SQLServer里面很容易實現(xiàn)剩瓶,而在Oracle里面需要通過游標進行處理。
下面存儲過程腳本城丧,是基于返回單條記錄的存儲過程延曙。
------------------------------------
--作者:伍華聰 http://wuhuacong.cnblogs.com
--創(chuàng)建時間:2014年11月27日
--功能描述:以字段ID為關鍵字,檢索表中的數據
------------------------------------
CREATE PROCEDURE dbo.T_Customer_SelectByID
(
@ID varchar(50)
)
AS
Select * from dbo.T_Customer Where ID= @ID
go
4)提供查詢處理亡哄,并返回多條記錄集合枝缔;包括實體列表集合或DataTable集合對象
對于返回多條集合的對象,在存儲過程里面體現(xiàn)都一樣的蚊惯,我們可能在C#處理的時候愿卸,把它轉換為不同的對象即可,返回多個集合截型,在SQLServer里面趴荸,它們的存儲過程代碼如下所示。
------------------------------------
--作者:伍華聰 http://wuhuacong.cnblogs.com
--創(chuàng)建時間:2014年11月27日
--功能描述:檢索表中所有的數據
------------------------------------
CREATE PROCEDURE dbo.T_Customer_SelectAll
AS
Select * from dbo.T_Customer
go
2宦焦、Oracle存儲過程的編寫
對應客戶表T_Customer发钝,Oracle的創(chuàng)建腳本如下所示顿涣。
CREATE TABLE T_CUSTOMER (
ID VARCHAR2(100),
NAME VARCHAR2(50) NOT NULL ,
AGE INTEGER NOT NULL,
CREATOR VARCHAR2(50) NULL,
CREATETIME DATE DEFAULT SYSDATE,
);
ALTER TABLE T_CUSTOMER ADD CONSTRAINT PK_T_CUSTOMER PRIMARY KEY (ID);
對應SQLServer的存儲過程,Oracle的存儲過程也提供了對應的版本酝豪,下面是幾種情況下的Oracle存儲過程的編寫涛碑。
1)提供執(zhí)行處理,可對執(zhí)行結果進行反饋
------------------------------------
--作者:伍華聰 http://wuhuacong.cnblogs.com
--創(chuàng)建時間:2014年11月27日
--功能描述:插入數據到表中
------------------------------------
Create Or Replace Procedure T_Customer_Insert
(
p_ID IN T_CUSTOMER.ID%TYPE,
p_Name IN T_CUSTOMER.NAME%TYPE,
p_Age IN T_CUSTOMER.AGE%TYPE
)
AS
Begin
Insert into T_CUSTOMER( ID,NAME,AGE ) Values( p_ID,p_Name,p_Age ) ;
Commit;
Exception
When Others Then
Rollback;
End;
/
------------------------------------
--作者:伍華聰 http://wuhuacong.cnblogs.com
--創(chuàng)建時間:2014年11月27日
--功能描述:以字段ID為關鍵字孵淘,修改表中的數據
------------------------------------
Create Or Replace Procedure T_Customer_UpdateByID
(
p_ID IN T_CUSTOMER.ID%TYPE,
p_Name IN T_CUSTOMER.NAME%TYPE,
p_Age IN T_CUSTOMER.AGE%TYPE
)
AS
Begin
Update T_CUSTOMER Set NAME=p_Name,AGE=p_Age Where ID= p_ID ;
Commit;
Exception
When Others Then
Rollback;
End;
/
------------------------------------
--作者:伍華聰 http://wuhuacong.cnblogs.com
--創(chuàng)建時間:2014年11月27日
--功能描述:以字段ID為關鍵字蒲障,刪除表的記錄
------------------------------------
Create Or Replace Procedure T_Customer_DeleteByID
(
p_ID IN T_CUSTOMER.ID%TYPE
)
AS
Begin
Delete From T_CUSTOMER where ID=p_ID ;
Commit;
Exception
When Others Then
Rollback;
End;
/
其中上面的代碼涉及幾個地方,T_CUSTOMER.ID%TYPE是表示根據字段動態(tài)決定參數的類型夺英,避免應硬編碼或者反復修改參數類型晌涕。
Oracle的參數一般使用p_的前綴開始,方便區(qū)分痛悯。
2)提供執(zhí)行處理余黎,獲得一個或者多個返回性參數,并可對執(zhí)行結果進行反饋载萌。
------------------------------------
--作者:伍華聰 http://wuhuacong.cnblogs.com
--創(chuàng)建時間:2014年11月27日
--功能描述:以字段ID為關鍵字惧财,檢查表中是否存在符合條件的記錄
------------------------------------
Create Or Replace Procedure T_Customer_ExistByID
(
p_Exist OUT Number ,
p_ID IN T_CUSTOMER.ID%TYPE
)
AS
Begin
--V9.i以下使用的語句
Select Case When (Count(1)>0) Then 1 Else 0 End Into p_Exist From T_CUSTOMER Where ID=p_ID ;
--也可以使用的語句
-- Select Decode(Count(1),0,0,1) Into p_Exist From T_CUSTOMER Where ID=p_ID ;
End;
/
------------------------------------
--作者:伍華聰 http://wuhuacong.cnblogs.com
--創(chuàng)建時間:2014年11月27日
--功能描述:獲取表用來標識字段的最大ID值,在標識ID非自增字段時可用于數據插入時調用
------------------------------------
Create Or Replace Procedure T_Customer_MaxAge
(
p_MaxAge OUT Number
)
AS
Begin
Select Decode(Max(Age) ,NULL,0,Max(Age)) Into p_MaxAge From T_CUSTOMER;
End;
/
上面的代碼扭仁,都有一個輸出的參數垮衷,雖然他們執(zhí)行沒有影響記錄函數,但是這個主要是通過輸出參數的值進行處理了乖坠。
3)提供查詢處理搀突,并返回實體對象
提供查詢處理,不管返回一條記錄熊泵,還是多條記錄仰迁,在Oracle里面,一般都是通過游標進行處理的顽分,因此我們需要先定義一個游標類型徐许,供我們返回記錄使用的。
下面定義一個游標的包代碼如下卒蘸。
------------------------------------
--作者:伍華聰 http://wuhuacong.cnblogs.com
--創(chuàng)建時間:2014年11月27日
--功能描述:創(chuàng)建一個包雌隅,含有一個游標類型:(一個數據庫中只需聲明一次)
------------------------------------
CREATE OR REPLACE PACKAGE MyCURSOR
AS
TYPE cur_OUT IS REF CURSOR;
End;
/
然后我們就可以在各個返回記錄的存儲過程里面使用這個游標類型了。
例如在下面的存儲過程里面缸沃,返回一條指定的數據記錄恰起,那么輸出參數里面需要有一個游標的定義參數,但是我們在C#里面使用數據訪問框架來處理數據的時候趾牧,可以忽略他它的存在村缸,就只需要輸入p_ID參數就可以了。
------------------------------------
--作者:伍華聰 http://wuhuacong.cnblogs.com
--創(chuàng)建時間:2014年11月27日
--功能描述:以字段ID為關鍵字武氓,檢索表中的數據
------------------------------------
Create Or Replace Procedure T_Customer_SelectByID
(
cur_OUT OUT MyCURSOR.cur_OUT ,
p_ID IN T_CUSTOMER.ID%TYPE
)
AS
Begin
OPEN cur_OUT FOR Select * from T_CUSTOMER Where ID = p_ID ;
End;
/
4)提供查詢處理梯皿,并返回多條記錄集合仇箱;包括實體列表集合或DataTable集合對象
和上面返回單條記錄一樣,需要返回多條記錄的存儲過程东羹,也需要使用一個游標的輸出參數來獲取返回的記錄剂桥,并可以對游標進行處理。
------------------------------------
--作者:伍華聰 http://wuhuacong.cnblogs.com
--創(chuàng)建時間:2014年11月27日
--功能描述:檢索表中所有的數據
------------------------------------
Create Or Replace Procedure T_Customer_SelectAll
( cur_OUT OUT MyCURSOR.cur_OUT )
AS
Begin
OPEN cur_OUT FOR Select * from T_CUSTOMER;
End;
/
最后属提,我們看看SQLServer和Oracle數據庫的腳本完整情況权逗。
SQLServer存儲過程代碼:
------------------------------------
--作者:伍華聰 http://wuhuacong.cnblogs.com
--創(chuàng)建時間:2014年11月27日
--功能描述:插入數據到表中
------------------------------------
CREATE PROCEDURE dbo.T_Customer_Insert
(
@ID varchar(50),
@Name varchar(50) ,
@Age int
)
AS
begin tran
Insert into dbo.T_Customer( ID,Name,Age ) Values( @ID,@Name,@Age )
if @@error!=0
begin
rollback
end
else
begin
commit
end
go
------------------------------------
--作者:伍華聰 http://wuhuacong.cnblogs.com
--創(chuàng)建時間:2014年11月27日
--功能描述:以字段ID為關鍵字,修改表中的數據
------------------------------------
CREATE PROCEDURE dbo.T_Customer_UpdateByID
(
@ID varchar(50),
@Name varchar(50) ,
@Age int
)
AS
begin tran
Update dbo.T_Customer Set Name=@Name,Age=@Age Where ID= @ID
if @@error!=0
begin
rollback
end
else
begin
commit
end
go
------------------------------------
--作者:伍華聰 http://wuhuacong.cnblogs.com
--創(chuàng)建時間:2014年11月27日
--功能描述:檢索表中所有的數據
------------------------------------
CREATE PROCEDURE dbo.T_Customer_SelectAll
AS
Select * from dbo.T_Customer
go
------------------------------------
--作者:伍華聰 http://wuhuacong.cnblogs.com
--創(chuàng)建時間:2014年11月27日
--功能描述:以字段ID為關鍵字冤议,檢索表中的數據
------------------------------------
CREATE PROCEDURE dbo.T_Customer_SelectByID
(
@ID varchar(50)
)
AS
Select * from dbo.T_Customer Where ID= @ID
go
------------------------------------
--作者:伍華聰 http://wuhuacong.cnblogs.com
--創(chuàng)建時間:2014年11月27日
--功能描述:以字段ID為關鍵字斟薇,檢查表中是否存在符合條件的記錄
------------------------------------
CREATE PROCEDURE dbo.T_Customer_ExistByID
(
@Exist int output ,
@ID varchar(50)
)
AS
Select @Exist = Case When Exists (Select 1 From dbo.T_Customer Where ID=@ID) Then 1 Else 0 End
go
------------------------------------
--作者:伍華聰 http://wuhuacong.cnblogs.com
--創(chuàng)建時間:2014年11月27日
--功能描述:以字段ID為關鍵字,刪除表的記錄
------------------------------------
CREATE PROCEDURE dbo.T_Customer_DeleteByID
(
@ID varchar(50)
)
AS
begin tran
Delete From dbo.T_Customer where ID=@ID
if @@error!=0
begin
rollback
end
else
begin
commit
end
go
------------------------------------
--作者:伍華聰 http://wuhuacong.cnblogs.com
--創(chuàng)建時間:2014年11月27日
--功能描述:獲取客戶最大年齡
------------------------------------
CREATE PROCEDURE dbo.T_Customer_MaxAge
( @MaxAge int output )
AS
Select @MaxAge=Case When Max(Age) is NULL Then 0 Else Max(Age) End From dbo.T_Customer
go
Oracle存儲過程代碼:
------------------------------------
--作者:伍華聰 http://wuhuacong.cnblogs.com
--創(chuàng)建時間:2014年11月27日
--功能描述:插入數據到表中
------------------------------------
Create Or Replace Procedure T_Customer_Insert
(
p_ID IN T_CUSTOMER.ID%TYPE,
p_Name IN T_CUSTOMER.NAME%TYPE,
p_Age IN T_CUSTOMER.AGE%TYPE
)
AS
Begin
Insert into T_CUSTOMER( ID,NAME,AGE ) Values( p_ID,p_Name,p_Age ) ;
Commit;
Exception
When Others Then
Rollback;
End;
/
------------------------------------
--作者:伍華聰 http://wuhuacong.cnblogs.com
--創(chuàng)建時間:2014年11月27日
--功能描述:以字段ID為關鍵字恕酸,修改表中的數據
------------------------------------
Create Or Replace Procedure T_Customer_UpdateByID
(
p_ID IN T_CUSTOMER.ID%TYPE,
p_Name IN T_CUSTOMER.NAME%TYPE,
p_Age IN T_CUSTOMER.AGE%TYPE
)
AS
Begin
Update T_CUSTOMER Set NAME=p_Name,AGE=p_Age Where ID= p_ID ;
Commit;
Exception
When Others Then
Rollback;
End;
/
------------------------------------
--作者:伍華聰 http://wuhuacong.cnblogs.com
--創(chuàng)建時間:2014年11月27日
--功能描述:創(chuàng)建一個包堪滨,含有一個游標類型:(一個數據庫中只需聲明一次)
------------------------------------
CREATE OR REPLACE PACKAGE MyCURSOR
AS
TYPE cur_OUT IS REF CURSOR;
End;
/
------------------------------------
--作者:伍華聰 http://wuhuacong.cnblogs.com
--創(chuàng)建時間:2014年11月27日
--功能描述:檢索表中所有的數據
------------------------------------
Create Or Replace Procedure T_Customer_SelectAll
( cur_OUT OUT MyCURSOR.cur_OUT )
AS
Begin
OPEN cur_OUT FOR Select * from T_CUSTOMER;
End;
/
------------------------------------
--作者:伍華聰 http://wuhuacong.cnblogs.com
--創(chuàng)建時間:2014年11月27日
--功能描述:以字段ID為關鍵字,檢索表中的數據
------------------------------------
Create Or Replace Procedure T_Customer_SelectByID
(
cur_OUT OUT MyCURSOR.cur_OUT ,
p_ID IN T_CUSTOMER.ID%TYPE
)
AS
Begin
OPEN cur_OUT FOR Select * from T_CUSTOMER Where ID = p_ID ;
End;
/
------------------------------------
--作者:伍華聰 http://wuhuacong.cnblogs.com
--創(chuàng)建時間:2014年11月27日
--功能描述:以字段ID為關鍵字蕊温,檢查表中是否存在符合條件的記錄
------------------------------------
Create Or Replace Procedure T_Customer_ExistByID
(
p_Exist OUT Number ,
p_ID IN T_CUSTOMER.ID%TYPE
)
AS
Begin
--V9.i以下使用的語句
Select Case When (Count(1)>0) Then 1 Else 0 End Into p_Exist From T_CUSTOMER Where ID=p_ID ;
--V8.i及以下使用的語句
-- Select Decode(Count(1),0,0,1) Into p_Exist From T_CUSTOMER Where ID=p_ID ;
End;
/
------------------------------------
--作者:伍華聰 http://wuhuacong.cnblogs.com
--創(chuàng)建時間:2014年11月27日
--功能描述:以字段ID為關鍵字袱箱,刪除表的記錄
------------------------------------
Create Or Replace Procedure T_Customer_DeleteByID
(
p_ID IN T_CUSTOMER.ID%TYPE
)
AS
Begin
Delete From T_CUSTOMER where ID=p_ID ;
Commit;
Exception
When Others Then
Rollback;
End;
/
------------------------------------
--作者:伍華聰 http://wuhuacong.cnblogs.com
--創(chuàng)建時間:2014年11月27日
--功能描述:獲取表用來標識字段的最大ID值,在標識ID非自增字段時可用于數據插入時調用
------------------------------------
Create Or Replace Procedure T_Customer_MaxAge
(
p_MaxAge OUT Number
)
AS
Begin
Select Decode(Max(Age) ,NULL,0,Max(Age)) Into p_MaxAge From T_CUSTOMER;
End;
/
以上就是存儲過程編寫過程中的處理和對比义矛,下一篇將繼續(xù)介紹這個主體发笔,并針對性的介紹如何在C#底層數據訪問里面,對這些存儲過程的使用凉翻。