Winform開發(fā)框架之存儲過程的支持--存儲過程的實現(xiàn)和演化提煉(1)

在我前面很多篇關(guān)于框架設(shè)計和介紹的文章里面,大多數(shù)都是利用框架提供的基礎(chǔ)性API進行各種的操作,包括增刪改查、分頁等各種實現(xiàn)和其衍生的實現(xiàn),而這些實現(xiàn)絕大多數(shù)是基于SQL的標準操作實現(xiàn)的,由于框架的底層是利用了微軟企業(yè)庫Enterprise Library,因此框架也是很好的支持存儲過程的各種調(diào)用,不過由于整體性和數(shù)據(jù)庫遷移方面的考慮,建議一般使用標準的SQL操作而已,這樣能夠很大程度上保證數(shù)據(jù)庫可以很平滑過渡到其他數(shù)據(jù)庫,如Access、SQLite等單機版數(shù)據(jù)庫。但是,有時候我們提供對存儲過程的支持也是十分必要的,有些業(yè)務(wù)可能就只是固定在某種特定的數(shù)據(jù)庫上跑,如SQLServer、Oracle等這些支持存儲過程的關(guān)系型數(shù)據(jù)庫,有些業(yè)務(wù)可能還真的需要存儲過程的整體性的封裝;基于這個原因,我撰寫了這篇文章,力求從較為全面的角度上闡述存儲過程的編寫、實現(xiàn)和演化提煉方面做一個介紹。

1、SQLServer存儲過程的編寫

雖然存儲過程一般用于處理一些復(fù)雜的邏輯關(guān)系或者報表內(nèi)容,不過為了介紹方便,我們從幾個較為基礎(chǔ)的操作進行介紹。
我們以一個客戶表來進行對應(yīng)的存儲過程來介紹,先介紹客戶表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)
)

為了介紹存儲過程的編寫,我們以這個表的相關(guān)操作的存儲過程來進行介紹,存儲過程一般可以分為下面幾種情況。
1)提供執(zhí)行處理,可對執(zhí)行結(jié)果進行反饋
這種情況常??梢砸姷剑缈梢詫Σ迦?、更新、刪除等操作進行處理,并獲得執(zhí)行的結(jié)果,下面是這兩種存儲過程的代碼。

------------------------------------
--作者:伍華聰 http://wuhuacong.cnblogs.com
--創(chuàng)建時間:2014年11月27日 
--功能描述:插入數(shù)據(jù)到表中 
------------------------------------
 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為關(guān)鍵字,修改表中的數(shù)據(jù) 
------------------------------------
 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為關(guān)鍵字,刪除表的記錄 
------------------------------------
 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í)行處理,獲得一個或者多個返回性參數(shù),并可對執(zhí)行結(jié)果進行反饋。

基于上面的處理方式,我們可能還有一種情況,就是需要執(zhí)行存儲過程個,并返回對應(yīng)的返回參數(shù),我們可以在程序里面利用代碼獲取這些返回參數(shù)的數(shù)值,從而用作其他用途。

因此,這種操作,如要是獲取返回性參數(shù)的情況,如下所示是判斷記錄是否存在,以及獲取客戶最大年齡的兩個存儲過程。

------------------------------------
--作者:伍華聰 http://wuhuacong.cnblogs.com
--創(chuàng)建時間:2014年11月27日 
--功能描述:以字段ID為關(guān)鍵字,檢查表中是否存在符合條件的記錄 
------------------------------------
 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é)后面介紹的內(nèi)容,都是存儲過程的返回值,這些或者是一條記錄,或者是多條記錄的查詢結(jié)果,這個在SQLServer里面很容易實現(xiàn),而在Oracle里面需要通過游標進行處理。

下面存儲過程腳本,是基于返回單條記錄的存儲過程。

------------------------------------
--作者:伍華聰 http://wuhuacong.cnblogs.com
--創(chuàng)建時間:2014年11月27日 
--功能描述:以字段ID為關(guān)鍵字,檢索表中的數(shù)據(jù) 
------------------------------------
 CREATE PROCEDURE dbo.T_Customer_SelectByID 
 ( 
      @ID varchar(50)
 ) 
 AS 
 Select * from dbo.T_Customer Where ID= @ID 
 go 

4)提供查詢處理,并返回多條記錄集合;包括實體列表集合或DataTable集合對象
對于返回多條集合的對象,在存儲過程里面體現(xiàn)都一樣的,我們可能在C#處理的時候,把它轉(zhuǎn)換為不同的對象即可,返回多個集合,在SQLServer里面,它們的存儲過程代碼如下所示。

------------------------------------
--作者:伍華聰 http://wuhuacong.cnblogs.com
--創(chuàng)建時間:2014年11月27日 
--功能描述:檢索表中所有的數(shù)據(jù) 
------------------------------------
 CREATE PROCEDURE dbo.T_Customer_SelectAll 
 AS 
 Select * from dbo.T_Customer 
 go 

2、Oracle存儲過程的編寫

對應(yīng)客戶表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);

對應(yīng)SQLServer的存儲過程,Oracle的存儲過程也提供了對應(yīng)的版本,下面是幾種情況下的Oracle存儲過程的編寫。
1)提供執(zhí)行處理,可對執(zhí)行結(jié)果進行反饋

------------------------------------
--作者:伍華聰 http://wuhuacong.cnblogs.com
--創(chuàng)建時間:2014年11月27日 
--功能描述:插入數(shù)據(jù)到表中 
------------------------------------
 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為關(guān)鍵字,修改表中的數(shù)據(jù) 
------------------------------------
 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為關(guān)鍵字,刪除表的記錄 
------------------------------------
 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是表示根據(jù)字段動態(tài)決定參數(shù)的類型,避免應(yīng)硬編碼或者反復(fù)修改參數(shù)類型。

Oracle的參數(shù)一般使用p_的前綴開始,方便區(qū)分。

2)提供執(zhí)行處理,獲得一個或者多個返回性參數(shù),并可對執(zhí)行結(jié)果進行反饋。

------------------------------------
--作者:伍華聰 http://wuhuacong.cnblogs.com
--創(chuàng)建時間:2014年11月27日 
--功能描述:以字段ID為關(guān)鍵字,檢查表中是否存在符合條件的記錄 
------------------------------------
 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非自增字段時可用于數(shù)據(jù)插入時調(diào)用 
------------------------------------
 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; 
 / 

上面的代碼,都有一個輸出的參數(shù),雖然他們執(zhí)行沒有影響記錄函數(shù),但是這個主要是通過輸出參數(shù)的值進行處理了。

3)提供查詢處理,并返回實體對象

提供查詢處理,不管返回一條記錄,還是多條記錄,在Oracle里面,一般都是通過游標進行處理的,因此我們需要先定義一個游標類型,供我們返回記錄使用的。

下面定義一個游標的包代碼如下。

------------------------------------
--作者:伍華聰 http://wuhuacong.cnblogs.com
--創(chuàng)建時間:2014年11月27日 
--功能描述:創(chuàng)建一個包,含有一個游標類型:(一個數(shù)據(jù)庫中只需聲明一次)  
------------------------------------
 CREATE OR REPLACE PACKAGE MyCURSOR 
 AS 
     TYPE cur_OUT IS REF CURSOR; 
 End; 
 / 

然后我們就可以在各個返回記錄的存儲過程里面使用這個游標類型了。

例如在下面的存儲過程里面,返回一條指定的數(shù)據(jù)記錄,那么輸出參數(shù)里面需要有一個游標的定義參數(shù),但是我們在C#里面使用數(shù)據(jù)訪問框架來處理數(shù)據(jù)的時候,可以忽略他它的存在,就只需要輸入p_ID參數(shù)就可以了。

------------------------------------
--作者:伍華聰 http://wuhuacong.cnblogs.com
--創(chuàng)建時間:2014年11月27日 
--功能描述:以字段ID為關(guān)鍵字,檢索表中的數(shù)據(jù) 
------------------------------------
 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集合對象

和上面返回單條記錄一樣,需要返回多條記錄的存儲過程,也需要使用一個游標的輸出參數(shù)來獲取返回的記錄,并可以對游標進行處理。

------------------------------------
--作者:伍華聰 http://wuhuacong.cnblogs.com
--創(chuàng)建時間:2014年11月27日 
--功能描述:檢索表中所有的數(shù)據(jù) 
------------------------------------
 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數(shù)據(jù)庫的腳本完整情況。

SQLServer存儲過程代碼:

------------------------------------
--作者:伍華聰 http://wuhuacong.cnblogs.com
--創(chuàng)建時間:2014年11月27日 
--功能描述:插入數(shù)據(jù)到表中 
------------------------------------
 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為關(guān)鍵字,修改表中的數(shù)據(jù) 
------------------------------------
 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日 
--功能描述:檢索表中所有的數(shù)據(jù) 
------------------------------------
 CREATE PROCEDURE dbo.T_Customer_SelectAll 
 AS 
 Select * from dbo.T_Customer 
 go 
 
------------------------------------
--作者:伍華聰 http://wuhuacong.cnblogs.com
--創(chuàng)建時間:2014年11月27日 
--功能描述:以字段ID為關(guān)鍵字,檢索表中的數(shù)據(jù) 
------------------------------------
 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為關(guān)鍵字,檢查表中是否存在符合條件的記錄 
------------------------------------
 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為關(guān)鍵字,刪除表的記錄 
------------------------------------
 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日 
--功能描述:插入數(shù)據(jù)到表中 
------------------------------------
 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為關(guān)鍵字,修改表中的數(shù)據(jù) 
------------------------------------
 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)建一個包,含有一個游標類型:(一個數(shù)據(jù)庫中只需聲明一次)  
------------------------------------
 CREATE OR REPLACE PACKAGE MyCURSOR 
 AS 
     TYPE cur_OUT IS REF CURSOR; 
 End; 
 / 
------------------------------------
--作者:伍華聰 http://wuhuacong.cnblogs.com
--創(chuàng)建時間:2014年11月27日 
--功能描述:檢索表中所有的數(shù)據(jù) 
------------------------------------
 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為關(guān)鍵字,檢索表中的數(shù)據(jù) 
------------------------------------
 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為關(guān)鍵字,檢查表中是否存在符合條件的記錄 
------------------------------------
 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為關(guān)鍵字,刪除表的記錄 
------------------------------------
 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非自增字段時可用于數(shù)據(jù)插入時調(diào)用 
------------------------------------
 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#底層數(shù)據(jù)訪問里面,對這些存儲過程的使用。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容