1. 程式人生 > 其它 >儲存過程詳解

儲存過程詳解

2019獨角獸企業重金招聘Python工程師標準>>> hot3.png

儲存過程簡介


什麼是儲存過程:儲存過程可以說是一個記錄集吧,它是由一些T-SQL語句組成的程式碼塊,這些T-SQL語句程式碼像一個方法一樣實現一些功能(對單表或多表的增刪改查),然後再給這個程式碼塊取一個名字,在用到這個功能的時候呼叫他就行了。

儲存過程的好處

1.由於資料庫執行動作時,是先編譯後執行的。然而儲存過程是一個編譯過的程式碼塊,所以執行效率要比T-SQL語句高。

2.一個儲存過程在程式在網路中互動時可以替代大堆的T-SQL語句,所以也能降低網路的通訊量,提高通訊速率。

3.通過儲存過程能夠使沒有許可權的使用者在控制之下間接地存取資料庫,從而確保資料的安全。


小結:總之儲存過程是好東西,在做專案時屬於必備利器,下面介紹儲存過程的基本語法。


儲存過程的語法和引數講解


儲存過程的一些基本語法:

複製程式碼

--------------建立儲存過程-----------------CREATEPROC[EDURE]procedure_name[;number]
[{@parameterdata_type}
[VARYING][=default][OUTPUT]
][,...n][WITH
{RECOMPILE|ENCRYPTION|RECOMPILE,ENCRYPTION}][FORREPLICATION]ASsql_statement[...n]--------------呼叫儲存過程-----------------EXECUTEProcedure_name''--儲存過程如果有引數,後面加引數格式為:@引數名=value,也可直接為引數值value--------------刪除儲存過程-----------------dropprocedureprocedure_name--在儲存過程中能呼叫另外一個儲存過程,而不能刪除另外一個儲存過程

複製程式碼

建立儲存過程的引數:
1.procedure_name :儲存過程的名稱,在前面加#為區域性臨時儲存過程,加##為全域性臨時儲存過程。

2.; number: 是可選的整數,用來對同名的過程分組,以便用一條 DROP PROCEDURE 語句即可將同組的過程一起除去。例如,名為 orders 的應用程式使用的過程可以命名為 orderproc;1、orderproc;2 等。DROP PROCEDURE orderproc 語句將除去整個組。如果名稱中包含定界識別符號,則數字不應包含在識別符號中,只應在 procedure_name 前後使用適當的定界符。

3.@parameter: 儲存過程的引數。可以有一個或多個。使用者必須在執行過程時提供每個所宣告引數的值(除非定義了該引數的預設值)。儲存過程最多可以有 2.100 個引數。

使 用 @ 符號作為第一個字元來指定引數名稱。引數名稱必須符合識別符號的規則。每個過程的引數僅用於該過程本身;相同的引數名稱可以用在其它過程中。預設情況下,參 數只能代替常量,而不能用於代替表名、列名或其它資料庫物件的名稱。有關更多資訊,請參見 EXECUTE。

4.data_type: 引數的資料型別。所有資料型別(包括 text、ntext 和 image)均可以用作儲存過程的引數。不過,cursor 資料型別只能用於 OUTPUT 引數。如果指定的資料型別為 cursor,也必須同時指定 VARYING 和 OUTPUT 關鍵字。有關 SQL Server 提供的資料型別及其語法的更多資訊,請參見資料型別。
說明 對於可以是 cursor 資料型別的輸出引數,沒有最大數目的限制。

5.VARYING: 指定作為輸出引數支援的結果集(由儲存過程動態構造,內容可以變化)。僅適用於遊標引數。

6.default: 引數的預設值。如果定義了預設值,不必指定該引數的值即可執行過程。預設值必須是常量或 NULL。如果過程將對該引數使用 LIKE 關鍵字,那麼預設值中可以包含萬用字元(%、_、[] 和 [^])。

7.OUTPUT:表明引數是返回引數。該選項的值可以返回給 EXEC[UTE]。使用 OUTPUT 引數可將資訊返回給呼叫過程。Text、ntext 和 image 引數可用作 OUTPUT 引數。使用 OUTPUT 關鍵字的輸出引數可以是遊標佔位符。

8.RECOMPILE: 表明 SQL Server 不會快取該過程的計劃,該過程將在執行時重新編譯。在使用非典型值或臨時值而不希望覆蓋快取在記憶體中的執行計劃時,請使用 RECOMPILE 選項。

9.ENCRYPTION:表 示 SQL Server 加密 syscomments 表中包含 CREATE PROCEDURE 語句文字的條目。使用 ENCRYPTION 可防止將過程作為 SQL Server 複製的一部分發布。 說明 在升級過程中,SQL Server 利用儲存在 syscomments 中的加密註釋來重新建立加密過程。

10.FOR REPLICATION :指定不能在訂閱伺服器上執行為複製建立的儲存過程。.使用 FOR REPLICATION 選項建立的儲存過程可用作儲存過程篩選,且只能在複製過程中執行。本選項不能和 WITH RECOMPILE 選項一起使用。

11.AS :指定過程要執行的操作。

12.sql_statement :過程中要包含的任意數目和型別的 Transact-SQL 語句。但有一些限制。

小結:看過這些基本語法後,下面我就根據語法建立各式的儲存過程。


建立儲存過程


UserAccount
UserID UserName PassWord RegisterTime RegisterIP
12 6 6 2012-12-31 6
18 5 5 2013-01-01 5
19 1 1 2013-01-01 1
20 2 2 2013-01-01 2
21 3 3 2013-01-01 3
22 4 4 2013-01-01 4
23 5 5 2013-01-01 5
25 7 7 2013-01-01 7
26 8 8 2013-01-01 8
NULL NULL NULL NULL NULL

針對上面的表,使用儲存過程對它做一些操作:


//建立表結構
CREATE TABLE [dbo].[UserAccount](
[UserID] [int] IDENTITY(1,1) NOT NULL,
[UserName] [varchar](10) NULL,
[PassWord] [varchar](10) NULL,
[RegisterTime] [varchar](20) NULL,
[RegisterIp] [int] NULL
) ON [PRIMARY]


TRUNCATE TABLE UserAccount; //清空UserAccount表

//插入資料
INSERT INTO UserAccount (UserName,PassWord,RegisterTime,RegisterIp) VALUES ('6','6','2012-12-31',6);
INSERT INTO UserAccount (UserName,PassWord,RegisterTime,RegisterIp) VALUES ('5','5','2013-01-01',5);
INSERT INTO UserAccount (UserName,PassWord,RegisterTime,RegisterIp) VALUES ('1','1','2013-01-01',1);
INSERT INTO UserAccount (UserName,PassWord,RegisterTime,RegisterIp) VALUES ('2','2','2013-01-01',2);
INSERT INTO UserAccount (UserName,PassWord,RegisterTime,RegisterIp) VALUES ('3','3','2013-01-01',3);
INSERT INTO UserAccount (UserName,PassWord,RegisterTime,RegisterIp) VALUES ('4','4','2013-01-01',4);
INSERT INTO UserAccount (UserName,PassWord,RegisterTime,RegisterIp) VALUES ('5','5','2013-01-01',5);
INSERT INTO UserAccount (UserName,PassWord,RegisterTime,RegisterIp) VALUES ('7','7','2013-01-01',7);
INSERT INTO UserAccount (UserName,PassWord,RegisterTime,RegisterIp) VALUES ('8','8','2013-01-01',8);

//查看錶中的資料
SELECT * FROM UserAccount;


//////////////////////////////////////////////////////////////////////////////
//////////////////////////////儲存過程案例////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////

///1. 只返回單一記錄集的儲存過程

-------------建立名為GetUserAccount的儲存過程----------------
create Procedure GetUserAccount
as
select * from UserAccount
go

-------------執行上面的儲存過程----------------
exec GetUserAccount
//結果:相當於執行 select * from UserAccount 這行程式碼,結果為整個表的資料。


///2.沒有輸入輸出的儲存過程

-------------建立名為GetUserAccount的儲存過程----------------
create Procedure inUserAccount
as
insert into UserAccount (UserName,[PassWord],RegisterTime,RegisterIP) values(9,9,'2013-01-02',9)
go

-------------執行上面的儲存過程----------------
exec inUserAccount
// 結果:相當於執行 insert into UserAccount (UserName,[PassWord],RegisterTime,RegisterIP) values(9,9,'2013-01-02',9) 這行程式碼。


///3.有返回值的儲存過程
-------------建立名為GetUserAccount的儲存過程----------------

create Procedure inUserAccountRe
as
insert into UserAccount (UserName,[PassWord],RegisterTime,RegisterIP) values(10,10,'2013-01-02',10)
return @@rowcount
go

-------------執行上面的儲存過程----------------

exec inUserAccountRe
// 解釋:這裡的@@rowcount為執行儲存過程影響的行數,執行的結果是不僅插入了一條資料,還返回了一個值即 return value =1 ,這個可以在程式中獲取,稍後在c#呼叫儲存過程中會有說到。


///4.有輸入引數和輸出引數的儲存過程
-------------建立名為GetUserAccount的儲存過程----------------

create Procedure GetUserAccountRe
@UserName nchar(20),
@UserID int output
as
if(@UserName>5)
select @UserID=COUNT(*) from UserAccount where UserID>25
else
set @UserID=1000
go

-------------執行上面的儲存過程----------------

exec GetUserAccountRe '7',NULL
//解釋:@UserName為輸入引數,@UserID為輸出引數。 執行結果為@userID為COOUT(*)即 =1。


///5. 同時具有返回值、輸入引數、輸出引數的儲存過程
-------------建立名為GetUserAccount的儲存過程----------------

create Procedure GetUserAccountRe1
@UserName nchar(20),
@UserID int output
as
if(@UserName>5)
select @UserID=COUNT(*) from UserAccount where UserID>25
else
set @UserID=1000
return @@rowcount
go

-------------執行上面的儲存過程----------------

exec GetUserAccountRe1 '7',NULL
//結果:@userID為COOUT(*)即 =1,Retun Value=1。


///6.同時返回引數和記錄集的儲存過程
-------------建立名為GetUserAccount的儲存過程----------------

create Procedure GetUserAccountRe2
@UserName nchar(20),
@UserID int output
as
if(@UserName>5)
select @UserID=COUNT(*) from UserAccount where UserID>25
else
set @UserID=1000
select * from UserAccount
return @@rowcount
go

-------------執行上面的儲存過程----------------

exec GetUserAccountRe2 '7',NULL
// 結果:返回執行 select * from UserAccount 這句程式碼的結果集,同時@userID為COOUT(*)即 =1,Retun Value=9。


///7.返回多個記錄集的儲存過程
-------------建立名為GetUserAccount的儲存過程----------------

create Procedure GetUserAccountRe3
as
select * from UserAccount
select * from UserAccount where UserID>5
go

-------------執行上面的儲存過程----------------

exec GetUserAccountRe3
//結果:返回兩個結果集,一個為 select * from UserAccount,另一個為 select * from UserAccount where UserID>5 。




轉載於:https://my.oschina.net/jackguo/blog/265251