SQLServer之建立儲存過程
建立儲存過程注意事項
在 SQL Server、 Azure SQL Database、Azure SQL 資料倉庫和並行資料庫中建立 Transact-SQL 或公共語言執行時 (CLR) 儲存過程,儲存過程與其他程式語言中的過程類似。
可以在當前資料庫中建立永久過程,或者在 tempdb 資料庫中建立臨時程式。
儲存過程可以:
-
接受輸入引數並以輸出引數的格式向呼叫過程或批處理返回多個值。
-
包含用於在資料庫中執行操作(包括呼叫其他過程)的程式設計語句。
-
向呼叫過程或批處理返回狀態值,以指明成功或失敗(以及失敗的原因)。
一般備註
一個過程沒有預定義的最大大小。
在過程中指定的變數可以是使用者定義變數或系統變數,如 @@SPID。
第一次執行某個過程時,將編譯該過程以確定檢索資料的最優訪問計劃。 如果已經生成的計劃仍保留在 資料庫引擎計劃快取中,則該過程隨後執行的操作可能重新使用該計劃。
SQL Server 啟動時可以自動執行一個或多個過程。 這些過程必須由系統管理員在 master 資料庫中建立,並以 sysadmin 固定伺服器角色作為後臺程序執行。 這些過程不能有任何輸入或輸出引數。 有關詳細資訊,請參閱執行儲存過程。
當一個過程通過引用 CLR 例程、型別或聚合來呼叫另一個過程或執行託管程式碼時,過程將被巢狀。 過程和託管程式碼引用的巢狀最高可達 32 級。 每當呼叫的過程或託管程式碼引用開始執行,巢狀級別就增加一級;執行完成後,巢狀級別就減少一級。 從託管程式碼內部呼叫的方法不根據巢狀級別限制進行計數。 但是,當一個 CLR 儲存過程通過 SQL Server 託管訪問介面執行資料訪問操作時,在從託管程式碼到 SQL 的轉換中將新增一級巢狀。
試圖超過最高階的巢狀將導致整個呼叫鏈失敗。 可以使用 @@NESTLEVEL 函式返回當前儲存過程執行的巢狀級別。
使用SSMS資料庫管理工具建立儲存過程語法和T-SQL指令碼建立儲存過程語法相同。
使用T-SQL指令碼建立儲存過程
語法:
--宣告資料庫引用
use 資料庫名;
go
--判斷是否存在儲存過程,如果存在則刪除
if exists(select * from sys.procedures where name=儲存過程名稱)
drop procedure 儲存過程名稱;
go
--建立儲存過程
create procedure [schema_name][.]procedure_name [;number]
[{ @parameter [type_schema_name.] data_type} [ null | not null ][varying] [ = default ] [ out| output ] [readonly] ] [,......n]
with [encryption][,][recompile][,][execute as clause]
for replication
as
begin
sql_statement;
end
go
語法解析:
--schema_name
--過程所屬架構的名稱。 過程是繫結到架構的。如果在建立過程時未指定架構名稱,則自動分配正在建立過程的使用者的預設架構。
--procedure_name
--過程的名稱。 過程名稱必須遵循有關識別符號的規則,並且在架構中必須唯一。
--在命名過程時避免使用 sp_ 字首。 此字首由 SQL Server 用來指定系統過程。 如果存在同名的系統過程,則使用字首可能導致應用程式程式碼中斷。
--可在 procedure_name 前面使用一個數字元號 (#procedure_name) 來建立區域性臨時程式,使用兩個數字符號 (##procedure_name) 來建立全域性臨時程式。
--區域性臨時程式僅對建立了它的連線可見,並且在關閉該連線後將被刪除。 全域性臨時程式可用於所有連線,並且在使用該過程的最後一個會話結束時將被刪除。 對於 CLR 過程,不能指定臨時名稱。
--過程或全域性臨時程式的完整名稱(包括 ##)不能超過 128 個字元。 區域性臨時程式的完整名稱(包括 #)不能超過 116 個字元。
--; number
--適用範圍: SQL Server 2008 到 SQL Server 2017 和 Azure SQL Database。
--用於對同名的過程分組的可選整數。 使用一個 DROP PROCEDURE 語句可將這些分組過程一起刪除。
[email protected]
--在過程中宣告的引數。 通過將 at 符號 (@) 用作第一個字元來指定引數名稱。 引數名稱必須符合識別符號規則。 每個過程的引數僅用於該過程本身;其他過程中可以使用相同的引數名稱。
--可宣告一個或多個引數;最大值是 2,100。 除非定義了引數的預設值或者將引數設定為等於另一個引數,否則使用者必須在呼叫過程時為每個宣告的引數提供值。
--如果過程包含表值引數,並且該引數在呼叫中缺失,則傳入空表。 引數只能代替常量表達式,而不能用於代替表名、列名或其他資料庫物件的名稱。 有關詳細資訊,請參閱 EXECUTE (Transact-SQL)。
--如果指定了 FOR REPLICATION,則無法宣告引數。
--[type_schema_name. [ =] data_type
--引數的資料型別以及該資料型別所屬的架構。
--針對 Transact-SQL 過程的準則:
--所有 Transact-SQL 資料型別都可以用作引數。
--您可以使用使用者定義的表型別建立表值引數。 表值引數只能是 INPUT 引數,並且這些引數必須帶有 READONLY 關鍵字。 有關詳細資訊,請參閱使用表值引數(資料引擎)
--遊標資料型別只能是 OUTPUT 引數,並且必須帶有 VARYING 關鍵字。
--針對 CLR 過程的準則:
--在託管程式碼中具有等效值的所有本機 SQL Server 資料型別都可以用作引數。 有關 CLR 型別與 SQL Server 系統資料型別之間關係的詳細資訊,請參閱對映 CLR 引數資料。 有關 SQL Server 系統資料型別及其語法的詳細資訊,請參閱資料型別 (Transact-SQL)。
--表值或遊標資料型別不能用作引數。
--如果引數的資料型別為 CLR 使用者定義型別,則必須對此型別有 EXECUTE 許可權。
--varying
--指定作為輸出引數支援的結果集。 該引數由過程動態構造,其內容可能發生改變。 僅適用於遊標引數。 該選項對於 CLR 過程無效。
--default
--引數的預設值。 如果為引數定義了預設值,則無需指定此引數的值即可執行過程。 預設值必須是常量或 NULL。 該常量值可以採用萬用字元的形式,這使其可以在將該引數傳遞到過程時使用 LIKE 關鍵字。
--只有 CLR 過程的預設值記錄在 sys.parameters.default 列中。 對於 Transact-SQL 過程引數,該列將為 NULL。
--out|output
--指示引數是輸出引數。 使用 OUTPUT 引數將值返回給過程的呼叫方。 除非是 CLR 過程,否則 text、ntext 和 image 引數不能用作 OUTPUT 引數。 OUTPUT 引數可以為遊標佔位符,CLR 過程除外。 不能將表值資料型別指定為過程的 OUTPUT 引數。
--readonly
--指示不能在過程的主體中更新或修改引數。 如果引數型別為表值型別,則必須指定 READONLY。
--encryption
--適用範圍:SQL Server( SQL Server 2008 到 SQL Server 2017)、 Azure SQL Database。
--指示 SQL Server 將 CREATE PROCEDURE 語句的原始文字轉換為模糊格式。 模糊程式碼的輸出在 SQL Server 的任何目錄檢視中都不能直接顯示。 對系統表或資料庫檔案沒有訪問許可權的使用者不能檢索模糊文字。
--但是,可以通過 DAC 埠訪問系統表的特權使用者或直接訪問資料檔案的特權使用者可以使用此文字。 此外,能夠向伺服器程序附加偵錯程式的使用者可在執行時從記憶體中檢索已解密的過程。 有關如何訪問系統元資料的詳細資訊,請參閱元資料可見性配置。
--該選項對於 CLR 過程無效。
--使用此選項建立的過程不能作為 SQL Server 複製的一部分發布。
--recompile
--指示 資料庫引擎不快取此過程的查詢計劃,這強制在每次執行此過程時都對該過程進行編譯。 有關強制重新編譯的原因的詳細資訊,請參閱重新編譯儲存過程。 在指定了 FOR REPLICATION 或者用於 CLR 過程時不能使用此選項。
--若要指示 資料庫引擎放棄過程內單個查詢的查詢計劃,請在該查詢的定義中使用 RECOMPILE 查詢提示。 有關詳細資訊,請參閱查詢提示 (Transact-SQL)。
--execute as 子句
--指定在其中執行過程的安全上下文。
--對於本機編譯儲存過程(從 SQL Server 2016 (13.x) 開始和在 Azure SQL Database 中),EXECUTE AS 子句沒有任何限制。 在 SQL Server 2014 (12.x) 中,對於本機編譯的儲存過程,支援 SELF、OWNER 和 ‘user_name’ 子句。
--有關詳細資訊,請參閱 EXECUTE AS 子句 (Transact-SQL)。
--SELF
--EXECUTE AS SELF 與 EXECUTE AS user_name 等價,其中指定使用者是建立或更改模組的使用者。 建立或更改模組的使用者的實際使用者 ID 儲存在 sys.sql_modules 或 sys.service_queues 目錄檢視的 execute_as_principal_id 列中。
--OWNER
--指定模組內的語句在模組的當前所有者上下文中執行。 如果模組沒有指定的所有者,則使用模組架構的所有者。 不能為 DDL 或登入觸發器指定 OWNER。
--' user_name '
--指定模組內的語句在 user_name 指定的使用者的上下文中執行。 將根據 user_name 來驗證對模組內任意物件的許可權。 不能為具有伺服器作用域的 DDL 觸發器或登入觸發器指定 user_name。 請改用 login_name。
--user_name 必須存在於當前資料庫中,並且必須是單一例項帳戶。 user_name 不能為組、角色、證書、金鑰或內建帳戶,如 NT AUTHORITY\LocalService、NT AUTHORITY\NetworkService 或 NT AUTHORITY\LocalSystem。
--執行上下文的使用者 ID 儲存在元資料中,可以在 sys.sql_modules 或 sys.assembly_modules 目錄檢視的 execute_as_principal_id 列檢視。
--' login_name '
--指定模組內的語句在 login_name 指定的 SQL Server 登入的上下文中執行。 將根據 login_name 來驗證對模組內任意物件的許可權。 只能為具有伺服器作用域的 DDL 觸發器或登入觸發器指定 login_name。
--login_name 不能為組、角色、證書、金鑰或內建帳戶,如 NT AUTHORITY\LocalService、NT AUTHORITY\NetworkService 或 NT AUTHORITY\LocalSystem。
--for replication
--適用範圍:SQL Server( SQL Server 2008 到 SQL Server 2017)、 Azure SQL Database。
--指定為複製建立該過程。 因此,它不能在訂閱伺服器上執行。 使用 FOR REPLICATION 選項建立的過程可用作過程篩選器,且僅在複製過程中執行。 如果指定了 FOR REPLICATION,則無法宣告引數。 對於 CLR 過程,不能指定 FOR REPLICATION。 對於使用 FOR REPLICATION 建立的過程,忽略 RECOMPILE 選項。
--FOR REPLICATION 過程在 sys.objects 和 sys.procedures 中包含 RF 物件型別。
--{ [ BEGIN ] sql_statement [;] [ ...n ] [ END ] }
--構成過程主體的一個或多個 Transact-SQL 語句。 您可以使用可選的 BEGIN 和 END 關鍵字將這些語句括起來。 有關資訊,請參閱後面的“最佳實踐”、“一般備註”以及“限制和侷限”部分。
示例:
--宣告資料庫引用
use testss;
go
--判斷是否存在儲存過程,如果存在則刪除
if exists(select * from sys.procedures where name='noreference')
drop procedure noreference;
go
--建立儲存過程
create procedure noreference
;1
@testid int=NULL,@outparameter varchar(100) out
with encryption,recompile,execute as owner
--for replication
as
begin
if @testid is not null
begin
select * from test1 where [email protected];
set @outparameter='有引數指定輸出';
end
else
begin
select * from test1;
set @outparameter='無引數輸出全部';
end
end
go