存儲過程(stored procedure)有時也稱sproc,它是真正的腳本,更准確地說,它是批處理(batch),但都不是很確切,它存儲與數據庫而不是單獨的文件中。
存儲過程中有輸入參數,輸出參數以及返回值等。
TestTalb
CREATE TABLE [dbo].[TrackLog]( [Id] [int] IDENTITY(1,1) NOT NULL, [FullName] [varchar](200) NOT NULL, [MethodName] [varchar](50) NOT NULL, [ExecuteTime] [time](3) NULL, [RowDate] [datetime] NULL, [Status] [varchar](50) NULL, [Message] [text] NULL, [ClientIP] [varchar](50) NULL, [CityCode] [varchar](10) NULL ) ON [PRIMARY] TEXTIMAGE_ON [PRIMARY]
Test數據語句 (Sql數據導出成腳本文件方法參考:http://jingyan.baidu.com/article/2a138328b594ea074a134f0c.html)
INSERT [dbo].[TrackLog] ([Id], [FullName], [MethodName], [ExecuteTime], [RowDate], [Status], [Message], [ClientIP], [CityCode]) VALUES (1, N'CentaNet.Mobile.Model.Request.GetBizGlobalRequest', N'GetBizGlobalRequest', CAST(0x03A0000000000000 AS Time), CAST(0x0000A65E00F637A7 AS DateTime), N'OK', N'', N'::1', N'0755') INSERT [dbo].[TrackLog] ([Id], [FullName], [MethodName], [ExecuteTime], [RowDate], [Status], [Message], [ClientIP], [CityCode]) VALUES (2, N'CentaNet.Mobile.Model.Request.GetBizGlobalRequest', N'GetBizGlobalRequest', CAST(0x0300000000000000 AS Time), CAST(0x0000A65E00F68B6C AS DateTime), N'OK', N'', N'::1', N'0755') INSERT [dbo].[TrackLog] ([Id], [FullName], [MethodName], [ExecuteTime], [RowDate], [Status], [Message], [ClientIP], [CityCode]) VALUES (3, N'CentaNet.Mobile.Model.Request.GetBizGlobalRequest', N'GetBizGlobalRequest', CAST(0x0300000000000000 AS Time), CAST(0x0000A65E00F68DBF AS DateTime), N'OK', N'', N'::1', N'0755') INSERT [dbo].[TrackLog] ([Id], [FullName], [MethodName], [ExecuteTime], [RowDate], [Status], [Message], [ClientIP], [CityCode]) VALUES (4, N'CentaNet.Mobile.Model.Request.GetBizGlobalRequest', N'GetBizGlobalRequest', CAST(0x0300000000000000 AS Time), CAST(0x0000A65E00F68F63 AS DateTime), N'OK', N'', N'::1', N'0755') INSERT [dbo].[TrackLog] ([Id], [FullName], [MethodName], [ExecuteTime], [RowDate], [Status], [Message], [ClientIP], [CityCode]) VALUES (5, N'CentaNet.Mobile.Model.Request.GetBizGlobalRequest', N'GetBizGlobalRequest', CAST(0x0300000000000000 AS Time), CAST(0x0000A65E00F6903F AS DateTime), N'OK', N'', N'::1', N'0755') INSERT [dbo].[TrackLog] ([Id], [FullName], [MethodName], [ExecuteTime], [RowDate], [Status], [Message], [ClientIP], [CityCode]) VALUES (6, N'CentaNet.Mobile.Model.Request.GetBizGlobalRequest', N'GetBizGlobalRequest', CAST(0x03C4000000000000 AS Time), CAST(0x0000A65E00F9927A AS DateTime), N'OK', N'', N'::1', NULL) INSERT [dbo].[TrackLog] ([Id], [FullName], [MethodName], [ExecuteTime], [RowDate], [Status], [Message], [ClientIP], [CityCode]) VALUES (7, N'CentaNet.Mobile.Model.Request.GetBizGlobalRequest', N'GetBizGlobalRequest', CAST(0x0300000000000000 AS Time), CAST(0x0000A65E00F9AA2F AS DateTime), N'OK', N'', N'::1', NULL) INSERT [dbo].[TrackLog] ([Id], [FullName], [MethodName], [ExecuteTime], [RowDate], [Status], [Message], [ClientIP], [CityCode]) VALUES (8, N'CentaNet.Mobile.Model.Request.GetBizGlobalRequest', N'GetBizGlobalRequest', CAST(0x03AB310000000000 AS Time), CAST(0x0000A65E00F9DCB8 AS DateTime), N'OK', N'', N'::1', NULL) INSERT [dbo].[TrackLog] ([Id], [FullName], [MethodName], [ExecuteTime], [RowDate], [Status], [Message], [ClientIP], [CityCode]) VALUES (9, N'CentaNet.Mobile.Model.Request.GetRegionEstatesRequest', N'GetRegionEstatesRequest', CAST(0x03DC000000000000 AS Time), CAST(0x0000A65E01219AAC AS DateTime), N'OK', N'', N'::1', NULL) INSERT [dbo].[TrackLog] ([Id], [FullName], [MethodName], [ExecuteTime], [RowDate], [Status], [Message], [ClientIP], [CityCode]) VALUES (10, N'CentaNet.Mobile.Model.Request.GetRegionEstatesRequest', N'GetRegionEstatesRequest', CAST(0x0309030000000000 AS Time), CAST(0x0000A65E0123B6E8 AS DateTime), N'OK', N'', N'::1', NULL) INSERT [dbo].[TrackLog] ([Id], [FullName], [MethodName], [ExecuteTime], [RowDate], [Status], [Message], [ClientIP], [CityCode]) VALUES (11, N'CentaNet.Mobile.Model.Request.GetRegionEstatesRequest', N'GetRegionEstatesRequest', CAST(0x03A6000000000000 AS Time), CAST(0x0000A65E01242AEC AS DateTime), N'OK', N'', N'::1', NULL) INSERT [dbo].[TrackLog] ([Id], [FullName], [MethodName], [ExecuteTime], [RowDate], [Status], [Message], [ClientIP], [CityCode]) VALUES (12, N'CentaNet.Mobile.Model.Request.GetRegionEstatesRequest', N'GetRegionEstatesRequest', CAST(0x03F6010000000000 AS Time), CAST(0x0000A65E01256628 AS DateTime), N'OK', N'', N'::1', NULL) INSERT [dbo].[TrackLog] ([Id], [FullName], [MethodName], [ExecuteTime], [RowDate], [Status], [Message], [ClientIP], [CityCode]) VALUES (13, N'CentaNet.Mobile.Model.Request.GetRegionEstatesRequest', N'GetRegionEstatesRequest', CAST(0x0305020000000000 AS Time), CAST(0x0000A65E0125C3E8 AS DateTime), N'OK', N'', N'::1', NULL) INSERT [dbo].[TrackLog] ([Id], [FullName], [MethodName], [ExecuteTime], [RowDate], [Status], [Message], [ClientIP], [CityCode]) VALUES (14, N'CentaNet.Mobile.Model.Request.GetRegionEstatesRequest', N'GetRegionEstatesRequest', CAST(0x039D000000000000 AS Time), CAST(0x0000A65E0125E5E4 AS DateTime), N'OK', N'', N'::1', NULL) INSERT [dbo].[TrackLog] ([Id], [FullName], [MethodName], [ExecuteTime], [RowDate], [Status], [Message], [ClientIP], [CityCode]) VALUES (15, N'CentaNet.Mobile.Model.Request.GetRegionEstatesRequest', N'GetRegionEstatesRequest', CAST(0x039D000000000000 AS Time), CAST(0x0000A65E01261398 AS DateTime), N'OK', N'', N'::1', NULL) INSERT [dbo].[TrackLog] ([Id], [FullName], [MethodName], [ExecuteTime], [RowDate], [Status], [Message], [ClientIP], [CityCode]) VALUES (16, N'CentaNet.Mobile.Model.Request.GetRegionEstatesRequest', N'GetRegionEstatesRequest', CAST(0x033C0E0000000000 AS Time), CAST(0x0000A65E015A71E3 AS DateTime), N'OK', N'', N'::1', NULL)
創建存儲過程
CREATE PROCEDURE|PROC <sproc name> [<parameter name> [schema.] <data type> [VARYING] [=<default value>] [OUT[PUT]] [READONLY] [,<parameter name> [schema.] <data type> [VARYING] [=<default value>] [OUT[PUT]] [READONLY] [,... ... ]] [WITH RECOMPILE | ENCRYPTION | [EXECUTE AS { CALLER | SELF | OWNER | <'user name'>}] AS <code> | EXTERNAL NAME <assembly name>.<assembly class>.<method>
簡單的存儲過程創建語句
CREATE PROCEDURE TEST_proc AS SELECT * FROM [Test].[dbo].[TrackLog]
存儲過程的執行
EXEC TEST_proc
存儲過程的修改
ALTER PROCEDURE|PROC <sproc name> [<parameter name> [schema.] <data type> [VARYING] [=<default value>] [OUT[PUT]] [READONLY] [,<parameter name> [schema.] <data type> [VARYING] [=<default value>] [OUT[PUT]] [READONLY] [,... ... ]] [WITH RECOMPILE | ENCRYPTION | [EXECUTE AS { CALLER | SELF | OWNER | <'user name'>}] AS <code> | EXTERNAL NAME <assembly name>.<assembly class>.<method>
存儲過程的刪除
DROP proc|procedure TEST_proc
存儲過程參數化
1、聲明參數
參數一般包含 名稱 數據類型 默認值 方向 @paremeter_name as datatype [default|null] [output|out]
-----------創建帶帶參數的存儲過程
CREATE PROCEDURE TEST_proc @sp_name nvarchar(50) AS SELECT * FROM [Test].[dbo].[TrackLog] where FullName like @sp_name+'%'
-----------執行帶參數的存儲過程 EXEC TEST_proc 'CentaNet.Mobile';
2、提供默認值
CREATE PROCEDURE TEST_proc @sp_name nvarchar(50)='CentaNet.Mobile.Model.Request.GetBizGlobalRequest' AS SELECT * FROM [Test].[dbo].[TrackLog] where FullName like @sp_name+'%' EXEC TEST_proc ;
3、輸出參數
------創建帶輸入輸出參數的存儲過程----------------
ALTER PROCEDURE test_procOut(@sp_id nvarchar(10),@fullname nvarchar(100) output) as select @fullname=fullname from dbo.TrackLog t where id =@sp_id
-------帶輸出參數的存儲過程的執行------------------ declare @fullname nvarchar(100) ----聲明輸出參數的 exec test_procOut 1,@fullname output ------調用存儲過程
print @fullname ---打印輸出參數的值
返回值
RETURN [<integer value to return>]
返回值必須是整數
關於RETURN語句,最重要的是知道它是無條件地從存儲過程中退出的。無論運行到存儲過程的哪個位置,在調用RETURN語句之后將不會執行任何一行代碼。
首先運行CREATE PROC過程。這回解析查詢以確保會實際運行這些代碼。它與直接運行腳本的區別在於CREATE PROC命令可以利用所謂的延遲名稱解析。延遲名稱解析可以忽略一些對象還不存在的事實。
在創建了存儲過程后,它將等待第一次執行。在那時,存儲過程被優化,而查詢計划被編譯並且緩存到系統上。后續幾次運行該存儲過程時,除非通過使用WITH RECOMPILE選項指定,否則都會使用緩存的查詢計划而不是創建一個新的查詢計划。這意味着每次使用該存儲過程時,存儲過程都會跳過很多優化和編譯工作。節省的確切時間取決於批處理的復雜性,批處理中表的大小,以及每個表上索引的數量。通常,節省的時間不是很多。但對於大多數場景來說可能是1秒或更少-但通過百分比可以計算出此區別(1秒比2秒快了100%)。當需要進行多次調用時或針對循環的情況,這一區別會變得更明顯。
存儲過程的不利方面
對於存儲過程的不利之處要認識到的最重要的一點事,除非手動地干預(使用WITH RECOMPILE選項),否則只會在第一次運行存儲過程的時候,或者當查詢所涉及的表更新了統計信息時,才對存儲過程進行優化。
這種"一次優化,多次使用"的策略節省了存儲過程的時間,但是該策略也是一把雙刃劍。如果查詢是動態的(即是在使用EXEC命令時建立的),那么只會在第一次運行時對存儲過程進行優化,但是會發現以后再也不這樣了。簡而言之,可能會使用錯誤的計划
WITH RECOMPILE選項
可以利用存儲過程提供的安全性代碼和代碼封裝方面的好處,但還是忽略了預編譯代碼方面的影響。可以回避未使用正確的查詢計划的問題,因為可以確保為特定一次運行創建新的計划。方法就是使用WITH RECOMPILE選項。
使用該選項的方式有兩種:
1、可以在運行時包含WITH RECOMPILE。
EXEC spMySproc '1/1/2004' WITH RECOMPILE
這告訴SQL Server拋棄已有的執行計划並且創建一個新的計划-但只是這一次。也就是說,只是這次使用WITH RECOMPILE選項來執行存儲過程。
也可以通過在存儲過程中包含WITH RECOMPILE選項來使之變得更持久。如果使用這種方式,則在CREATE PROC或ALTER PROC語句中的AS語句前添加WITH RECOMPILE選項即可。
如果通過該選項創建存儲過程,那么無論在運行時選擇了其他什么選項,每次運行存儲過程都會重新編譯它。
系統存儲過程
的在於能夠方便的從系統表中查詢信息或完成與更新數據庫表相關的管理任務或其他的系統管理任務。系統存儲過程主要存儲在master數據庫中,以“sp”下划線開頭的存儲過程。盡管這些系統存儲過程在master數據庫中,但我們在其他數據庫還是可以調用系統存儲過程。有一些系統存儲過程會在創建新的數據庫的時候被自動創建在當前數據庫中。
常用系統存儲過程有:
exec sp_databases; --查看數據庫 exec sp_tables; --查看表 exec sp_columns student;--查看列 exec sp_helpIndex student;--查看索引 exec sp_helpConstraint student;--約束 exec sp_stored_procedures; exec sp_helptext 'sp_stored_procedures';--查看存儲過程創建、定義語句 exec sp_rename student, stuInfo;--修改表、索引、列的名稱 exec sp_renamedb myTempDB, myDB;--更改數據庫名稱 exec sp_defaultdb 'master', 'myDB';--更改登錄名的默認數據庫 exec sp_helpdb;--數據庫幫助,查詢數據庫信息 exec sp_helpdb master; 系統存儲過程示例: --表重命名 exec sp_rename 'stu', 'stud'; select * from stud; --列重命名 exec sp_rename 'stud.name', 'sName', 'column'; exec sp_help 'stud'; --重命名索引 exec sp_rename N'student.idx_cid', N'idx_cidd', N'index'; exec sp_help 'student'; --查詢所有存儲過程 select * from sys.objects where type = 'P'; select * from sys.objects where type_desc like '%pro%' and name like 'sp%';