- --1.1創建無參數存儲過程
- --這個存儲過程的定義很像視圖定義
- create procedure dbo.usp_wct
- as
- select wcId,
- wcV,
- wcDate
- from wcT
- go
- --1.2執行存儲過程
- exec dbo.usp_wct
- --2.1創建帶參數的存儲過程
- create procedure dbo.usp_param_wct
- (@wcId bigint =1, --默認值爲1
- @wcDate datetime =null) --默認值爲null
- as
- select wcV
- from dbo.wcT
- where wcId = @wcId
- and isnull(@wcDate,1)=case when @wcdate is null
- then 1
- else wcDate
- end
- --返回狀態值,一般不用於返回計算結果,而是用來返回表明存儲過程執行的狀態
- return 1
- go
- --2.2.1調用存儲過程
- exec dbo.usp_param_wct '1','2012-07-01'
- --2.2.2調用存儲過程,帶參數名
- exec dbo.usp_param_wct @wcid='1',
- @wcdate='2012-07-01'
- --2.2.3調用存儲過程,帶參數名,只輸入一個參數值,另一個會使用默認值
- exec dbo.usp_param_wct @wcid='1'
- --2.2.4調用存儲過程,帶參數名,不輸入參數,2個參數都會使用默認值
- exec dbo.usp_param_wct
- --3.1創建帶output參數的存儲過程
- create procedure dbo.usp_output_param_wct
- (@wcId bigint =1, --默認值爲1
- @wcDate datetime =null, --默認值爲null
- @wcV varchar(50) output) --輸出參數,用來返回計算結果
- as
- select @wcV = wcV
- from dbo.wcT
- where wcId = @wcId
- and isnull(@wcDate,1)=case when @wcdate is null
- then 1
- else wcDate
- end
- --返回狀態值,一般不用於返回計算結果,而是用來返回表明存儲過程執行的狀態
- return 1
- go
- --3.2調用存儲過程
- declare @output varchar(50)
- exec dbo.usp_output_param_wct @wcId =1, --輸入參數
- --@wcDate = null,
- @wcv = @output output --輸出參數,存放返回值
- print @output
- --4.1修改存儲過程
- create procedure dbo.usp_output_param_wct
- (@wcId bigint =1, --默認值爲1
- @wcDate datetime =null, --默認值爲null
- @wcV varchar(50) output) --輸出參數,用來返回計算結果
- with encryption --加密存儲過程
- as
- select @wcV = wcV
- from dbo.wcT
- where wcId = @wcId
- and isnull(@wcDate,1)=case when @wcdate is null
- then 1
- else wcDate
- end
- --返回狀態值,一般不用於返回計算結果,而是用來返回表明存儲過程執行的狀態
- return 1
- go
- --4.2查看定義
- select object_name(object_id),
- definition --顯示爲NULL
- from sys.sql_modules
- where object_id = object_id('dbo.usp_output_param_wct')
- --5.在SQL Server啓動時自動執行存儲過程
- create procedure dbo.create_table
- as
- select * into wc.dbo.wcX
- from wc.dbo.wcT
- go
- --5.1設置爲true,在SQL Server啓動時自動執行存儲過程
- exec sp_procoption @procname = 'dbo.create_table',
- @optionname = 'startup',
- @optionvalue= 'true'
- --5.2設置爲false來禁止
- --只有dbo擁有的master數據庫中的對象才能更改啓動設置。
- use master
- go
- exec sp_procoption @procname = 'dbo.create_table',
- @optionname = 'startup',
- @optionvalue= 'false'
- --6.1每次存儲過程執行時都重新編譯
- --需要注意的是:當表、索引數據大量更新時,會進行語句級別的重新編譯
- create procedure dbo.usp_backupset_info
- (@startDate datetime,
- @finishDate datetime)
- with recompile --不保存執行計劃,每次都是重新編譯
- as
- select SUM(backup_size)/1024/1024/1024 as 'GB'
- from msdb.dbo.backupset
- where backup_start_date >= @startDate
- and backup_finish_date <= @finishDate
- and type = 'D' --數據庫備份,不是日誌備份或差異備份
- go
- --6.2清空過程緩存
- select *
- from sys.dm_exec_cached_plans
- dbcc freeproccache --清空過程緩存
- --再次查詢發現都已經清空
- select *
- from sys.dm_exec_cached_plans
- --7.刷新存儲過程,查看元數據
- exec sp_refreshsqlmodule @name ='dbo.usp_output_param_wct'
- select p.name, --存儲過程名稱
- p.object_id,
- pp.parameter_id,
- pp.name, --參數名稱
- pp.default_value, --好像不起作用
- t.name --參數列的類型
- from sys.procedures p
- inner join sys.parameters pp
- on pp.object_id = p.object_id
- inner join sys.types t
- on t.system_type_id = pp.system_type_id
- where p.object_id =965578478
- --8.刪除存儲過程
- DROP PROCEDURE dbo.usp_output_param_wct
存儲過程的Execute as選項
- --1.創建表
- create table dbo.wcE
- (vid int not null primary key clustered,
- v int not null
- )
- insert into dbo.wcE
- values(1,100),
- (2,200),
- (3,300)
- --2.創建存儲過程,存儲過程的架構與存儲過程中引用對象的架構一樣
- create procedure dbo.usp_delete_wcE
- as
- delete from dbo.wcE
- go
- --3.1創建登錄名
- create login wclogin with password = 'wclogin123'
- --3.2創建數據庫用戶
- create user wclogin
- --4.授予用戶執行存儲過程的權限
- grant exec on dbo.usp_delete_wcE to wclogin
- grant connect to wclogin
- /*====================================================
- 5.1打開另一個客戶端,以wclogin登錄名登進去,然後執行存儲過程,
- 雖然這個用戶沒有訪問存儲過程中所引用表的權限,
- 但是由於存儲過程的架構與存儲過程中引用對象的架構一樣,
- 同時由於存儲過程中只能是insert,update,delete,select,
- 而不能是trancate等操作,這就是所有權鏈,所以沒有報錯.
- 特別需要注意的是:以上的所有權鏈對於動態的SQL是無效的.
- ======================================================*/
- exec dbo.usp_delete_wcE
- --5.2這裏改爲truncate後,會報錯
- alter procedure dbo.usp_delete_wcE
- as
- truncate table dbo.wcE
- go
- --6.1使用execute as owner指定存儲過程的任何調用,
- --都是在存儲過程架構的擁有者的安全上下文運行的
- --這時再次以wclogin登錄就可以執行存儲過程而不會報錯
- alter procedure dbo.usp_delete_wcE
- with execute as owner
- as
- truncate table dbo.wcE
- go
- --6.2以執行用戶的權限來執行存儲過程
- --在以wclogin登錄執行時會報錯
- alter procedure dbo.usp_delete_wcE
- with execute as caller
- as
- truncate table dbo.wcE
- go
- --6.3以創建或最近一次更新存儲過程的用戶的權限來執行存儲過程,
- --在以wclogin登錄執行時會報錯
- alter procedure dbo.usp_delete_wcE
- with execute as self
- as
- truncate table dbo.wcE
- go
- --6.4以指定的用戶的權限來執行存儲過程,
- --在以wclogin登錄執行時顯然不會報錯
- alter procedure dbo.usp_delete_wcE
- with execute as 'dbo'
- as
- truncate table dbo.wcE
- go
- --6.5這個存儲過程用了動態的SQL語句
- create procedure dbo.w
- as
- exec('select * from dbo.wcE');
- go
- grant exec on dbo.w to wclogin
- --在客戶端以wclogin登錄,執行時會報錯
- --拒絕了對對象'wcE'(數據庫'wc',架構'dbo')的SELECT權限。
- exec dbo.w
- --1.函數
- if exists(select * from sys.objects where name = 'f_splitSTR' and type = 'tf')
- drop function dbo.f_splitSTR
- go
- create function dbo.f_splitSTR
- (
- @s varchar(8000), --要分拆的字符串
- @split varchar(10) --分隔字符
- )
- returns @re table( --要返回的臨時表
- col varchar(1000) --臨時表中的列
- )
- as
- begin
- declare @len int
- set @len = LEN(@split) --分隔符不一定就是一個字符,可能是2個字符
- while CHARINDEX(@split,@s) >0
- begin
- insert into @re
- values(left(@s,charindex(@split,@s) - 1))
- set @s = STUFF(@s,1,charindex(@split,@s) - 1 + @len ,'') --覆蓋:字符串以及分隔符
- end
- insert into @re values(@s)
- return --返回臨時表
- end
- go
- select * from dbo.f_splitSTR('123,456',',')
- --2.存儲過程
- --創建類型
- create type var_orgid as table
- (
- org_id numeric(10,0)
- )
- --創建存儲過程
- create proc usp_orgid
- @orgid_table var_orgid readonly
- as
- select * from @orgid_table
- go
- --定義表變量
- declare @orgid_table as var_orgid
- insert into @orgid_table
- values(123)
- exec usp_orgid @orgid_table
sp_executesql存儲過程,可以使動態語句重用,提高效率:
- DECLARE @sumcount INT
- DECLARE @tmpSQL NVARCHAR(1000)
- DECLARE @TABLENAME VARCHAR(50)
- SELECT @TABLENAME = ' sys.objects ' --表名變量賦值
- SELECT @tmpSQL = 'select @sum = convert(varchar(50),count(object_id)) from ' + @TABLENAME
- /*
- 參數1: 動態語句
- 參數2:定義的參數,這個參數就是在動態語句中引用到的變量@sum
- 參數3:指明瞭執行結果@sum的值,放到@sumcount參數裏面,
- 這裏需要特別注意的是,動態語句中的變量,和外面定義的變量,是不同的,
- 下面的語句,實際相當於:
- declare @sum int
- select @sum = convert(varchar(50),count(object_id))
- from + 表名
- 所以,通過sp_executesql,可以把語句產生的結果輸出到外面的變量,
- 這樣我們才能知道輸結果
- */
- exec sp_executesql @tmpsql,
- N'@sum int output',
- @sumcount out
- select @sumcount
try catch 錯誤處理
- create proc proc_t(@i int)
- as
- select 5 * 1.0 / @i
- go
- --1.不會報錯
- begin try
- begin tran
- exec proc_t 1
- select '執行成功'
- commit tran
- end try
- begin catch
- select '執行失敗'
- if @@trancount >0
- rollback
- end catch
- --2.這次會報錯,因爲分母爲0
- begin try
- begin tran
- exec proc_t 0
- select '執行成功'
- commit tran
- end try
- begin catch
- select '執行失敗'
- if @@trancount >0
- rollback
- end catch