日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 编程资源 > 综合教程 >内容正文

综合教程

T-SQL 之 存储过程

發(fā)布時間:2024/9/5 综合教程 41 生活家
生活随笔 收集整理的這篇文章主要介紹了 T-SQL 之 存储过程 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.

  當(dāng)存儲過程執(zhí)行一次后,可以將語句緩存中,這樣下次執(zhí)行的時候直接使用緩存中的語句。這樣就可以提高存儲過程的性能。

一、存儲過程的概念

存儲過程Procedure是一組為了完成特定功能的SQL語句集合,經(jīng)編譯后存儲在數(shù)據(jù)庫中,用戶通過指定存儲過程的名稱并給出參數(shù)來執(zhí)行。

存儲過程中可以包含邏輯控制語句和數(shù)據(jù)操縱語句,它可以接受參數(shù)、輸出參數(shù)、返回單個或多個結(jié)果集以及返回值。

由于存儲過程在創(chuàng)建時即在數(shù)據(jù)庫服務(wù)器上進(jìn)行了編譯并存儲在數(shù)據(jù)庫中,所以存儲過程運(yùn)行要比單個的SQL語句塊要快。同時由于在調(diào)用時只需用提供存儲過程名和必要的參數(shù)信息,所以在一定程度上也可以減少網(wǎng)絡(luò)流量、簡單網(wǎng)絡(luò)負(fù)擔(dān)。

  1、 存儲過程的優(yōu)點(diǎn)

  [1] 存儲過程允許標(biāo)準(zhǔn)組件式編程

  存儲過程創(chuàng)建后可以在程序中被多次調(diào)用執(zhí)行,而不必重新編寫該存儲過程的SQL語句。而且數(shù)據(jù)庫專業(yè)人員可以隨時對存儲過程進(jìn)行修改,但對應(yīng)用程序源代碼卻毫無影響,從而極大的提高了程序的可移植性。

  [2] 存儲過程能夠?qū)崿F(xiàn)較快的執(zhí)行速度

如果某一操作包含大量的T-SQL語句代碼,分別被多次執(zhí)行,那么存儲過程要比批處理的執(zhí)行速度快得多。因?yàn)榇鎯^程是預(yù)編譯的,在首次運(yùn)行一個存儲過程時,查詢優(yōu)化器對其進(jìn)行分析、優(yōu)化,并給出最終被存在系統(tǒng)表中的存儲計(jì)劃。而批處理的T-SQL語句每次運(yùn)行都需要預(yù)編譯和優(yōu)化,所以速度就要慢一些。

  [3] 存儲過程減輕網(wǎng)絡(luò)流量

  對于同一個針對數(shù)據(jù)庫對象的操作,如果這一操作所涉及到的T-SQL語句被組織成一存儲過程,那么當(dāng)在客戶機(jī)上調(diào)用該存儲過程時,網(wǎng)絡(luò)中傳遞的只是該調(diào)用語句,否則將會是多條SQL語句。從而減輕了網(wǎng)絡(luò)流量,降低了網(wǎng)絡(luò)負(fù)載。

  [4] 存儲過程可被作為一種安全機(jī)制來充分利用

  系統(tǒng)管理員可以對執(zhí)行的某一個存儲過程進(jìn)行權(quán)限限制,從而能夠?qū)崿F(xiàn)對某些數(shù)據(jù)訪問的限制,避免非授權(quán)用戶對數(shù)據(jù)的訪問,保證數(shù)據(jù)的安全。

二、創(chuàng)建存儲過程的基本語法

---------------------------創(chuàng)建存儲過程-----------------------
CREATE PROC[ EDURE ] procedure_name [ ; number ]
    [ { @Parameter Datatype }[ VARYING ] [ = default ] [|OUT|OUTPUT]] 
    ......
    [ WITH { RECOMPILE | ENCRYPTION | RECOMPILE , ENCRYPTION } ]
    [ FOR REPLICATION ]
AS
BEGIN
    sql_statement [ ...n ]
END
--------------調(diào)用存儲過程-----------------
--存儲過程如果有參數(shù),后面加參數(shù)格式為:@參數(shù)名=value,也可直接為參數(shù)值value
EXECUTE Procedure_name

--------------刪除存儲過程-----------------
--在存儲過程中能調(diào)用另外一個存儲過程,而不能刪除另外一個存儲過程
IF (EXISTS (SELECT * FROM sys.objects WHERE name = 'procedure_name'))
DROP PROCEDURE procedure_name 

創(chuàng)建存儲過程的參數(shù):
  1、procedure_name :存儲過程的名稱,在前面加#為局部臨時存儲過程,加##為全局臨時存儲過程。
  2、; number:是可選的整數(shù),用來對同名的過程分組,以便用一條 DROP PROCEDURE 語句即可將同組的過程一起除去。例如,名為 orders 的應(yīng)用程序使用的過程可以命名為 orderproc;1、orderproc;2 等。DROP PROCEDURE orderproc 語句將除去整個組。如果名稱中包含定界標(biāo)識符,則數(shù)字不應(yīng)包含在標(biāo)識符中,只應(yīng)在 procedure_name 前后使用適當(dāng)?shù)亩ń绶?
  3、@Parameter: 存儲過程的參數(shù)。可以有0-多個。用戶必須在執(zhí)行過程時提供每個所聲明參數(shù)的值(除非定義了該參數(shù)的默認(rèn)值)。存儲過程最多可以有 100 個參數(shù)。
  使用 @ 符號作為第一個字符來指定參數(shù)名稱。參數(shù)名稱必須符合標(biāo)識符的規(guī)則。每個過程的參數(shù)僅用于該過程本身;相同的參數(shù)名稱可以用在其它過程中。默認(rèn)情況下,參數(shù)只能代替常量,而不能用于代替表名、列名或其它數(shù)據(jù)庫對象的名稱。有關(guān)更多信息,請參見 EXECUTE。
  4、Datatype:參數(shù)的數(shù)據(jù)類型。所有數(shù)據(jù)類型(包括 text、ntext 和 image)均可以用作存儲過程的參數(shù)。不過,cursor 數(shù)據(jù)類型只能用于 OUTPUT 參數(shù)。如果指定的數(shù)據(jù)類型為 cursor,也必須同時指定 VARYING 和 OUTPUT 關(guān)鍵字。有關(guān) SQL Server 提供的數(shù)據(jù)類型及其語法的更多信息,請參見數(shù)據(jù)類型。
  說明:對于可以是 cursor 數(shù)據(jù)類型的輸出參數(shù),沒有最大數(shù)目的限制。
  5、VARYING: 指定作為輸出參數(shù)支持的結(jié)果集(由存儲過程動態(tài)構(gòu)造,內(nèi)容可以變化)。僅適用于游標(biāo)參數(shù)。

  6、default: 參數(shù)的默認(rèn)值。如果定義了默認(rèn)值,不必指定該參數(shù)的值即可執(zhí)行過程。默認(rèn)值必須是常量或 NULL。如果過程將對該參數(shù)使用 LIKE 關(guān)鍵字,那么默認(rèn)值中可以包含通配符(%、_、[] 和 [^])。

  7、OUTPUT:表明參數(shù)是返回參數(shù)。該選項(xiàng)的值可以返回給 EXEC[UTE]。使用 OUTPUT 參數(shù)可將信息返回給調(diào)用過程。Text、ntext 和 image 參數(shù)可用作 OUTPUT 參數(shù)。使用 OUTPUT 關(guān)鍵字的輸出參數(shù)可以是游標(biāo)占位符。

  8、RECOMPILE: 表明 SQL Server 不會緩存該過程的計(jì)劃,該過程將在運(yùn)行時重新編譯。在使用非典型值或臨時值而不希望覆蓋緩存在內(nèi)存中的執(zhí)行計(jì)劃時,請使用 RECOMPILE 選項(xiàng)。

  9、ENCRYPTION:表示 SQL Server 加密 syscomments 表中包含 CREATE PROCEDURE 語句文本的條目。使用 ENCRYPTION 可防止將過程作為 SQL Server 復(fù)制的一部分發(fā)布。 說明 在升級過程中,SQL Server 利用存儲在 syscomments 中的加密注釋來重新創(chuàng)建加密過程。

  10、FOR REPLICATION :指定不能在訂閱服務(wù)器上執(zhí)行為復(fù)制創(chuàng)建的存儲過程。.使用 FOR REPLICATION 選項(xiàng)創(chuàng)建的存儲過程可用作存儲過程篩選,且只能在復(fù)制過程中執(zhí)行。本選項(xiàng)不能和 WITH RECOMPILE 選項(xiàng)一起使用。

  11、AS :指定過程要執(zhí)行的操作。

  12、sql_statement :過程中要包含的任意數(shù)目和類型的 Transact-SQL 語句。但有一些限制。

二、ALTER修改存儲過程

  ALTER PROC和CREATE PROC的區(qū)別如下:

  [1] ALTER PROC期望找到一個已有的存儲過程,而CREATE則不是。

  [2] ALTER PROC保留了存儲過程上已經(jīng)建立的任何權(quán)限。它在系統(tǒng)對象中保留了對象Id并允許保留依賴關(guān)系。例如,如果過程A調(diào)用過程B,如果刪除并重建B,那么就不能在看到這兩者間的依賴關(guān)系。如果使用ALTER,則依賴關(guān)系仍然存在。

  [3] ALTER PROC在可能調(diào)用被修改的存儲過程的其他對象上保留了任何依賴信息。

  示例:

ALTER PROC spPerson
AS
SELECT * FROM Person WHERE Id = 45

三、刪除存儲過程

  刪除存儲過程的語法最簡單:

DROP PROC|PROCEDURE <sproc name>[;]

四、參數(shù)化

  如果存儲過程沒有辦法接受一些數(shù)據(jù),告訴其要完成的任務(wù),則在大多數(shù)情況下,存儲過程不會有太大幫助。例如,要刪除一條數(shù)據(jù),但卻不指定Id,則存儲過程也不知道要刪除哪條,所以使用輸入?yún)?shù)非常有必要。

  1、聲明參數(shù)

  語法如下:

@parameter_name [AS] datatype [=default|NULL] [VARYING] [OUTPUT | OUT]

  參數(shù)名稱,有一組簡單的規(guī)則。首先,它必須以@符號(和變量一樣)開始。此外,除了不能內(nèi)嵌空格外,其規(guī)則與普通變量規(guī)則相同。

  數(shù)據(jù)類型和名稱一樣,必須像變量那樣聲明,采用SQL Server內(nèi)置的或用戶自定義的數(shù)據(jù)類型。

  聲明需要類型時需要注意,當(dāng)聲明CURSOR類型參數(shù)時,必須也使用VARYING和OUTPUT選項(xiàng)。同時,OUTPUT可以簡寫為OUT。

  在默認(rèn)值方面,參數(shù)與變量不同。對于同樣的情況,變量一般初始化為NULL值,而參數(shù)不是。事實(shí)上,如果不提供默認(rèn)則,則會假設(shè)參數(shù)是必須的,并且當(dāng)調(diào)用存儲過程時需要提供一個初始值。

五、返回值

  返回值的用途非常廣泛,例如,返回數(shù)據(jù),標(biāo)識值或是存儲過程影響的行數(shù)等等。而其實(shí)際作用是返回值可用來確定存儲過程執(zhí)行的狀態(tài)。

  事實(shí)上,不管是否提供返回值,程序都會收到一個返回值。SQL Server默認(rèn)會在完成存儲過程時自動返回一個0值。

  為了從存儲過程向調(diào)用代碼傳遞返回值,只需要使用RETURN語句。

  RETURN [<integer value to return>]

  要特別注意的是:返回值必須是整數(shù)

  關(guān)于RETURN語句,最重要的是知道它是無條件地從存儲過程中退出的。無論運(yùn)行到存儲過程的哪個位置,在調(diào)用RETURN語句之后將不會執(zhí)行任何一行代碼。

  這里的無條件,并不是說無論執(zhí)行到代碼的何處都將執(zhí)行RETURN語句。相反,可以再存儲過程中有多個RETURN語句。只有當(dāng)代碼的標(biāo)準(zhǔn)條件結(jié)構(gòu)發(fā)出命令的時候,才會執(zhí)行這些RETURN語句。一旦發(fā)生,就不能再退回了。

六、存儲過程的優(yōu)缺點(diǎn)

  1、創(chuàng)建可調(diào)用的進(jìn)程

  很多人并沒有意識到要充分使用存儲過程,使其作為實(shí)現(xiàn)安全性的工具。和視圖類似,可以創(chuàng)建一個返回記錄集的存儲過程而不用賦予用戶訪問底層數(shù)據(jù)表的權(quán)限。賦予某人執(zhí)行一個存儲過程的權(quán)限意味著他們可以在該存儲過程中執(zhí)行任何動作。不過要假設(shè)動作是在存儲過程的上下文中執(zhí)行的。

  2、存儲過程和性能

  一般來說,存儲過程有助于系統(tǒng)性能的提高。但是,如果設(shè)計(jì)的存儲過程缺乏只能,那么它會使在其創(chuàng)建的進(jìn)程變得非常緩慢。

  存儲過程的運(yùn)行示意圖如下:

  

  首先運(yùn)行CREATE PROC過程。這回解析查詢以確保會實(shí)際運(yùn)行這些代碼。它與直接運(yùn)行腳本的區(qū)別在于CREATE PROC命令可以利用所謂的延遲名稱解析。延遲名稱解析可以忽略一些對象還不存在的事實(shí)。

  在創(chuàng)建了存儲過程后,它將等待第一次執(zhí)行。在那時,存儲過程被優(yōu)化,而查詢計(jì)劃被編譯并且緩存到系統(tǒng)上。后續(xù)幾次運(yùn)行該存儲過程時,除非通過使用WITH RECOMPILE選項(xiàng)指定,否則都會使用緩存的查詢計(jì)劃而不是創(chuàng)建一個新的查詢計(jì)劃。這意味著每次使用該存儲過程時,存儲過程都會跳過很多優(yōu)化和編譯工作。節(jié)省的確切時間取決于批處理的復(fù)雜性,批處理中表的大小,以及每個表上索引的數(shù)量。通常,節(jié)省的時間不是很多。但對于大多數(shù)場景來說可能是1秒或更少-但通過百分比可以計(jì)算出此區(qū)別(1秒比2秒快了100%)。當(dāng)需要進(jìn)行多次調(diào)用時或針對循環(huán)的情況,這一區(qū)別會變得更明顯。

  3、存儲過程的不利方面

  對于存儲過程的不利之處要認(rèn)識到的最重要的一點(diǎn)事,除非手動地干預(yù)(使用WITH RECOMPILE選項(xiàng)),否則只會在第一次運(yùn)行存儲過程的時候,或者當(dāng)查詢所涉及的表更新了統(tǒng)計(jì)信息時,才對存儲過程進(jìn)行優(yōu)化。
  這種"一次優(yōu)化,多次使用"的策略節(jié)省了存儲過程的時間,但是該策略也是一把雙刃劍。如果查詢是動態(tài)的(即是在使用EXEC命令時建立的),那么只會在第一次運(yùn)行時對存儲過程進(jìn)行優(yōu)化,但是會發(fā)現(xiàn)以后再也不這樣了。簡而言之,可能會使用錯誤的計(jì)劃。

  4、WITH RECOMPILE選項(xiàng)

  可以利用存儲過程提供的安全性代碼和代碼封裝方面的好處,但還是忽略了預(yù)編譯代碼方面的影響。可以回避未使用正確的查詢計(jì)劃的問題,因?yàn)榭梢源_保為特定一次運(yùn)行創(chuàng)建新的計(jì)劃。方法就是使用WITH RECOMPILE選項(xiàng)。
  使用該選項(xiàng)的方式有兩種:

  1、可以在運(yùn)行時包含WITH RECOMPILE。

  EXEC spMySproc '1/1/2004'
  WITH RECOMPILE

  這告訴SQL Server拋棄已有的執(zhí)行計(jì)劃并且創(chuàng)建一個新的計(jì)劃-但只是這一次。也就是說,只是這次使用WITH RECOMPILE選項(xiàng)來執(zhí)行存儲過程。

  也可以通過在存儲過程中包含WITH RECOMPILE選項(xiàng)來使之變得更持久。如果使用這種方式,則在CREATE PROC或ALTER PROC語句中的AS語句前添加WITH RECOMPILE選項(xiàng)即可。

  如果通過該選項(xiàng)創(chuàng)建存儲過程,那么無論在運(yùn)行時選擇了其他什么選項(xiàng),每次運(yùn)行存儲過程都會重新編譯它。

三、幾種特殊存儲過程

  1、 不緩存存儲過程

--WITH RECOMPILE 不緩存
if (object_id('proc_temp', 'P') is not null)
    drop proc proc_temp
go
create proc proc_temp
with recompile
as
    select * from student;
go

exec proc_temp;

  2、 加密存儲過程

--加密WITH ENCRYPTION 
if (object_id('proc_temp_encryption', 'P') is not null)
    drop proc proc_temp_encryption
go
create proc proc_temp_encryption
with encryption
as
    select * from student;
go

exec proc_temp_encryption;
exec sp_helptext 'proc_temp';
exec sp_helptext 'proc_temp_encryption';

  3、 帶游標(biāo)參數(shù)存儲過程

if (object_id('proc_cursor', 'P') is not null)
    drop proc proc_cursor
go
create proc proc_cursor
    @cur cursor varying output
as
    set @cur = cursor forward_only static for
    select id, name, age from student;
    open @cur;
go
--調(diào)用
declare @exec_cur cursor;
declare @id int,
        @name varchar(20),
        @age int;
exec proc_cursor @cur = @exec_cur output;--調(diào)用存儲過程
fetch next from @exec_cur into @id, @name, @age;
while (@@fetch_status = 0)
begin
    fetch next from @exec_cur into @id, @name, @age;
    print 'id: ' + convert(varchar, @id) + ', name: ' + @name + ', age: ' + convert(char, @age);
end
close @exec_cur;
deallocate @exec_cur;--刪除游標(biāo)

  4、 分頁存儲過程

---存儲過程、row_number完成分頁
if (object_id('pro_page', 'P') is not null)
    drop proc proc_cursor
go
create proc pro_page
    @startIndex int,
    @endIndex int
as
    select count(*) from product
;    
    select * from (
        select row_number() over(order by pid) as rowId, * from product 
    ) temp
    where temp.rowId between @startIndex and @endIndex
go
--drop proc pro_page
exec pro_page 1, 4
--
--分頁存儲過程
if (object_id('pro_page', 'P') is not null)
    drop proc pro_stu
go
create procedure pro_stu(
    @pageIndex int,
    @pageSize int
)
as
    declare @startRow int, @endRow int
    set @startRow = (@pageIndex - 1) * @pageSize +1
    set @endRow = @startRow + @pageSize -1
    select * from (
        select *, row_number() over (order by id asc) as number from student 
    ) t
    where t.number between @startRow and @endRow;

exec pro_stu 2, 2;

總結(jié)

以上是生活随笔為你收集整理的T-SQL 之 存储过程的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯,歡迎將生活随笔推薦給好友。