SQL Server 存儲過程

  存儲過程(stored procedure)有時也稱sproc,它是真正的腳本,更準確地說,它是批處理(batch),但都不是很確切,它存儲與數據庫而不是單獨的文件中。數據庫

  存儲過程當中有輸入參數,輸出參數以及返回值等。緩存

1、建立存儲過程安全

建立存儲過程的方法和建立數據庫中任何其餘對象同樣,除了他使用AS關鍵字外。存儲過程的基本語法以下:ide

  CREATEPROCEDURE|PROC<sproc name>[ [schema.]<data type>[VARYING][=][OUT[PUT]] [READONLY][, [schema.]<data type>[VARYING][=][OUT[PUT]] [READONLY][,...  ...      ]]  [WITH   RECOMPILE | ENCRYPTION | [EXECUTE AS { CALLER | SELF | OWNER | <'user name'>}]AS<code>| EXTERNAL NAME <assembly name>.<assembly class>.<method>工具

  在語法中,PROC是PROCEDURE的縮寫,兩個選項的意思同樣。性能

  在對存儲過程命名完以後,接着是參數列表。參數是可選的。優化

  關鍵字AS其後就是實際的代碼。spa

  簡單的存儲過程示例:設計

  CREATEPROC spPerson  ASSELECT*FROM Personcode

  執行存儲過程:

  EXEC spPerson

  查看結果:

2、ALTER修改存儲過程

ALTER PROC和CREATE PROC的區別以下:

  •   ALTER PROC指望找到一個已有的存儲過程,而CREATE則不是。

  •   ALTER PROC保留了存儲過程上已經創建的任何權限。它在系統對象中保留了對象Id並容許保留依賴關係。例如,若是過程A調用過程B,若是刪除並重建B,那麼就不能在看到這二者間的依賴關係。若是使用ALTER,則依賴關係仍然存在。

  •   ALTER PROC在可能調用被修改的存儲過程的其餘對象上保留了任何依賴信息。

  示例:

  ALTERPROC spPerson  ASSELECT*FROM Person WHERE Id =45

3、刪除存儲過程

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

  DROPPROC|PROCEDURE<sproc name>[;]

  這樣就完成了存儲過程的刪除。

4、參數化

  若是存儲過程沒有辦法接受一些數據,告訴其要完成的任務,則在大多數狀況下,存儲過程不會有太大幫助。例如,要刪除一條數據,但卻不指定Id,則存儲過程也不知道要刪除哪條,因此使用輸入參數很是有必要。

  一、聲明參數

  聲明參數須要如下2到4部分的信息:

  •   名稱

  •   數據類型

  •   默認值

  •   方向

  其語法以下所示:

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

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

  數據類型和名稱同樣,必須像變量那樣聲明,採用SQL Server內置的或用戶自定義的數據類型。

  聲明須要類型時須要注意,當聲明CURSOR類型參數時,必須也使用VARYING和OUTPUT選項。同時,OUTPUT能夠簡寫爲OUT。

  在默認值方面,參數與變量不一樣。對於一樣的狀況,變量通常初始化爲NULL值,而參數不是。事實上,若是不提供默認則,則會假設參數是必須的,而且當調用存儲過程時須要提供一個初始值。

  一個須要傳入參數的存儲過程示例:

  CREATEPROC spName    @Namenvarchar(50)  ASSELECT Name FROM Person  WHERE Name LIKE@Name+'%';

  執行存儲過程:

  EXEC spName '酒';

  顯示結果以下:

二、提供默認值

  爲了使參數是可選的,必須提供默認值。方法是在數據類型後在逗號以前添加"="符號和做爲默認值的值。這樣,存儲過程的用戶尅有決定對此參數不提供值或是提供他們本身的值。

   建立一個存儲過程以下:

  CREATEPROC spName  @Namenvarchar(50) =NULLASIF@NameISNOTNULLSELECT*FROM Person WHERE NAME =@NameELSESELECT*FROM Person WHERE Id =45

   執行以下語句:

  EXEC spName   EXEC spName '如意刀狼'

   輸出結果以下:

三、輸出參數

  下面來看看一個得到OUTPUT參數的存儲過程:

  CREATEPROC InsertPerson      @Idint OUTPUT  --必須註明爲OUTPUTASINSERTINTO Person  VALUES('劉備',22,190,'不詳','未婚','幼兒園','不詳',4999999)  SET@Id=@@IDENTITY

   執行存儲過程:

  DECLARE@Idint  --實際上,調用時名稱能夠不一樣,例如也能夠爲@Num,@i等等。EXEC InsertPerson @Id OUTPUT    --注意此處也要有OUTPUTSELECT@Id

  顯示結果以下:

  對於存儲過程自己以及調用腳本對它的使用,須要注意如下幾點:

  • 對於存儲過程聲明中的輸出參數,須要使用OUTPUT關鍵字。

  • 和聲明存儲過程時同樣,調用存儲過程時,必須使用OUTPUT關鍵字。這樣就對SQL Server做了提早通知,告訴它參數所須要的特殊處理。但須要注意的是,若是忘記包含OUTPUT關鍵字,不會產生運行時錯誤,可是輸出的值不會傳入變量中(變量極可能是NULL)。

  • 賦值給輸出結果的變量不須要和存儲過程當中的內部參數擁有相同的名稱。

  • EXEC(或EXECUTE)關鍵字是必須的,由於對存儲過程的調用並非批處理要作的第一件事(若是存儲過程的調用是批處理的第一件事,則能夠不使用EXEC)。

5、返回值

  返回值的用途很是普遍,例如,返回數據,標識值或是存儲過程影響的行數等等。而其實際做用是返回值可用來肯定存儲過程執行的狀態。

  事實上,無論是否提供返回值,程序都會收到一個返回值。SQL Server默認會在完成存儲過程時自動返回一個0值。

  爲了從存儲過程向調用代碼傳遞返回值,只須要使用RETURN語句。

  RETURN[]

  要特別注意的是:返回值必須是整數

  關於RETURN語句,最重要的是知道它是無條件地從存儲過程當中退出的。不管運行到存儲過程的哪一個位置,在調用RETURN語句以後將不會執行任何一行代碼。

  這裏的無條件,並非說不管執行到代碼的何處都將執行RETURN語句。相反,能夠再存儲過程當中有多個RETURN語句。只有當代碼的標準條件結構發出命令的時候,纔會執行這些RETURN語句。一旦發生,就不能再退回了。

  建立一個存儲過程以下:

  CREATEPROC spTestReturns  ASDECLARE@MyMessagenvarchar(50);  DECLARE@MyOtherMessagenvarchar(50);  SELECT@MyMessage='第一個RETURN';  PRINT@MyMessage;  RETURN;  SELECT@MyOtherMessage='第二個RETURN';  PRINT@MyOtherMessage;  RETURN;

  執行存儲過程,輸出以下:

  爲了能捕獲RETURN語句的值,須要在EXEC語句中把值賦給變量。例如:

  DECLARE@Returnint  EXEC@Return= spTestReturns  SELECT@Return

  輸出以下:

   雖然簡單可是還不錯。當運行時,能夠看到RETURN語句倒是在運行其餘代碼前終止了代碼運行。

   若是老是返回0,那麼執行成不成功都不知道,那麼咱們如今來改寫下上面的存儲過程,讓其返回一個指定的值,以指示執行狀態。

  CREATEPROC spTestReturns  ASDECLARE@MyMessagenvarchar(50);  DECLARE@MyOtherMessagenvarchar(50);  SELECT@MyMessage='第一個RETURN';  PRINT@MyMessage;      RETURN100;        --將這裏改爲返回100SELECT@MyOtherMessage='第二個RETURN';  PRINT@MyOtherMessage;  RETURN;

   執行以後,顯示結果以下:

6、存儲過程的優缺點

   存儲過程的主要優勢包括如下幾個方面:

  •   使得須要過程式動做的進程可調用

  •   安全性

  •   性能

一、建立可調用的進程

  不少人並無意識到要充分使用存儲過程,使其做爲實現安全性的工具。和視圖相似,能夠建立一個返回記錄集的存儲過程而不用賦予用戶訪問底層數據表的權限。賦予某人執行一個存儲過程的權限意味着他們能夠在該存儲過程當中執行任何動做。不過要假設動做是在存儲過程的上下文中執行的。

二、存儲過程和性能

  通常來講,存儲過程有助於系統性能的提升。可是,若是設計的存儲過程缺少只能,那麼它會使在其建立的進程變得很是緩慢。

  存儲過程的運行示意圖以下:

  首先運行CREATE PROC過程。這回解析查詢以確保會實際運行這些代碼。它與直接運行腳本的區別在於CREATE PROC命令能夠利用所謂的延遲名稱解析。延遲名稱解析能夠忽略一些對象還不存在的事實。

  在建立了存儲過程後,它將等待第一次執行。在那時,存儲過程被優化,而查詢計劃被編譯而且緩存到系統上。後續幾回運行該存儲過程時,除非經過使用WITH RECOMPILE選項指定,不然都會使用緩存的查詢計劃而不是建立一個新的查詢計劃。這意味着每次使用該存儲過程時,存儲過程都會跳過不少優化和編譯工做。節省的確切時間取決於批處理的複雜性,批處理中表的大小,以及每一個表上索引的數量。一般,節省的時間不是不少。但對於大多數場景來講多是1秒或更少-但經過百分比能夠計算出此區別(1秒比2秒快了100%)。當須要進行屢次調用時或針對循環的狀況,這一區別會變得更明顯。

三、存儲過程的不利方面

  對於存儲過程的不利之處要認識到的最重要的一點事,除非手動地干預(使用WITH RECOMPILE選項),不然只會在第一次運行存儲過程的時候,或者當查詢所涉及的表更新了統計信息時,纔對存儲過程進行優化。

  這種"一次優化,屢次使用"的策略節省了存儲過程的時間,可是該策略也是一把雙刃劍。若是查詢是動態的(便是在使用EXEC命令時創建的),那麼只會在第一次運行時對存儲過程進行優化,可是會發現之後不再這樣了。簡而言之,可能會使用錯誤的計劃。

四、WITH RECOMPILE選項

  能夠利用存儲過程提供的安全性代碼和代碼封裝方面的好處,但仍是忽略了預編譯代碼方面的影響。能夠迴避未使用正確的查詢計劃的問題,由於能夠確保爲特定一次運行建立新的計劃。方法就是使用WITH RECOMPILE選項。

  使用該選項的方式有兩種:

  一、能夠在運行時包含WITH RECOMPILE。

  EXEC spMySproc '1/1/2004'WITH RECOMPILE

  這告訴SQL Server拋棄已有的執行計劃而且建立一個新的計劃-但只是這一次。也就是說,只是此次使用WITH RECOMPILE選項來執行存儲過程。

  也能夠經過在存儲過程當中包含WITH RECOMPILE選項來使之變得更持久。若是使用這種方式,則在CREATE PROC或ALTER PROC語句中的AS語句前添加WITH RECOMPILE選項便可。

若是經過該選項建立存儲過程,那麼不管在運行時選擇了其餘什麼選項,每次運行存儲過程都會從新編譯它。

相關文章
相關標籤/搜索