存儲過程(Stored Procedure),是一組爲了完成特定功能的SQL 語句,相似一門程序設計語言,也包括了數據類型、流程控制、輸入和輸出和它本身的函數庫。存儲過程能夠說是一個記錄集,它是由一些T-SQL語句組成的代碼塊,這些T-SQL語句代碼像一個方法同樣實現一些功能(對單表或多表的增刪改查),而後再給這個代碼塊取一個名字,在用到這個功能的時候調用他就好了。不過SQL存儲過程對於一些初學者來講仍是比較抽象難理解的,所以本文將由淺至深地剖析SQL存儲過程,幫助你學習它。存儲過程的優勢 1.存儲過程只在創造時進行編譯,之後每次執行存儲過程都不需再從新編譯,而通常SQL語句每執行一次就編譯一次,因此使用存儲過程可提升數據庫執行速度,效率要比T-SQL語句高。2.當對數據庫進行復雜操做時,可將此複雜操做用存儲過程封裝起來與數據庫提供的事務處理結合一塊兒使用。三、一個存儲過程在程序在網絡中交互時能夠替代大堆的T-SQL語句,因此也能下降網絡的通訊量,提升通訊速率。4.存儲過程能夠重複使用,可減小數據庫開發人員的工做量。5.安全性高,可設定只有某些用戶才具備對指定存儲過程的使用權存儲過程基本語法--------------建立存儲過程----------------- CREATE PROC [ EDURE ] procedure_name [ ; number ] [ { @parameter data_type } [ VARYING ] [ = default ] [ OUTPUT ] ] [ ,...n ] [ WITH { RECOMPILE | ENCRYPTION | RECOMPILE , ENCRYPTION } ] [ FOR REPLICATION ] AS sql_statement [ ...n ] --------------調用存儲過程----------------- EXECUTE Procedure_name '' --存儲過程若是有參數,後面加參數格式爲:@參數名=value,也可直接爲參數值value --------------刪除存儲過程----------------- drop procedure procedure_name --在存儲過程當中能調用另一個存儲過程,而不能刪除另一個存儲過程建立存儲過程的參數1.procedure_name :存儲過程的名稱,在前面加#爲局部臨時存儲過程,加##爲全局臨時存儲過程。2.; number:是可選的整數,用來對同名的過程分組,以便用一條 DROP PROCEDURE 語句便可將同組的過程一塊兒除去。例如,名爲 orders 的應用程序使用的過程能夠命名爲 orderproc;一、orderproc;2 等。DROP PROCEDURE orderproc 語句將除去整個組。若是名稱中包含定界標識符,則數字不該包含在標識符中,只應在 procedure_name 先後使用適當的定界符。 3.@parameter:存儲過程的參數。能夠有一個或多個。用戶必須在執行過程時提供每一個所聲明參數的值(除非定義了該參數的默認值)。存儲過程最多能夠有 2100 個參數。 使用 @ 符號做爲第一個字符來指定參數名稱。參數名稱必須符合標識符的規則。每一個過程的參數僅用於該過程自己;相同的參數名稱能夠用在其它過程當中。默認狀況下,參數只能代替常量,而不能用於代替表名、列名或其它數據庫對象的名稱。有關更多信息,請參見 EXECUTE。 4.data_type:參數的數據類型。全部數據類型(包括 text、ntext 和 image)都可以用做存儲過程的參數。不過,cursor 數據類型只能用於 OUTPUT 參數。若是指定的數據類型爲 cursor,也必須同時指定 VARYING 和 OUTPUT 關鍵字。有關 SQL Server 提供的數據類型及其語法的更多信息,請參見數據類型。 說明 對於能夠是 cursor 數據類型的輸出參數,沒有最大數目的限制。 5.VARYING:指定做爲輸出參數支持的結果集(由存儲過程動態構造,內容能夠變化)。僅適用於遊標參數。 6.default: 參數的默認值。若是定義了默認值,沒必要指定該參數的值便可執行過程。默認值必須是常量或 NULL。若是過程將對該參數使用 LIKE 關鍵字,那麼默認值中能夠包含通配符(%、_、[] 和 [^])。7.OUTPUT:代表參數是返回參數。該選項的值能夠返回給 EXEC[UTE]。使用 OUTPUT 參數可將信息返回給調用過程。Text、ntext 和 image 參數可用做 OUTPUT 參數。使用 OUTPUT 關鍵字的輸出參數能夠是遊標佔位符。 8.RECOMPILE: 代表 SQL Server 不會緩存該過程的計劃,該過程將在運行時從新編譯。在使用非典型值或臨時值而不但願覆蓋緩存在內存中的執行計劃時,請使用 RECOMPILE 選項。9.ENCRYPTION: 表示 SQL Server 加密 syscomments 表中包含 CREATE PROCEDURE 語句文本的條目。使用 ENCRYPTION 可防止將過程做爲 SQL Server 複製的一部分發布。 說明在升級過程當中,SQL Server 利用存儲在 syscomments 中的加密註釋來從新建立加密過程。 10.FOR REPLICATION:指定不能在訂閱服務器上執行爲複製建立的存儲過程。.使用 FOR REPLICATION 選項建立的存儲過程可用做存儲過程篩選,且只能在複製過程當中執行。本選項不能和 WITH RECOMPILE 選項一塊兒使用。 11.AS:指定過程要執行的操做。12.sql_statement:過程當中要包含的任意數目和類型的 Transact-SQL 語句。但有一些限制。實例操做學習下面經過表Student來具體瞭解一下存儲過程,由於是要了解存儲過程的簡單用法,因此例子很簡單。無參數存儲過程:選出Student表中的全部信息 create proc StuProc as //此處 as 不能夠省略不寫 begin //begin 和 end 是一對,不能夠只寫其中一個,但能夠都不寫 select S#,Sname,Sage,Ssex from student end go 有參數存儲過程:全局變量全局變量也稱爲外部變量,是在函數的外部定義的,它的做用域爲從變量定義處開始,到本程序文件的末尾。選出指定姓名的學生信息: create proc StuProc @sname varchar(100) as begin select S#,Sname,Sage,Ssex from student where sname=@sname end go exec StuProc '趙雷' //執行語句 上面是在外部給變量賦值,也能夠在內部直接給變量設置默認值create proc StuProc @sname varchar(100)='趙雷' as begin select S#,Sname,Sage,Ssex from student where sname=@sname end go exec StuProc 也能夠把變量的內容輸出,使用outputcreate proc StuProc @sname varchar(100), @IsRight int output //傳出參數 as if exists (select S#,Sname,Sage,Ssex from student where sname=@sname) set @IsRight =1 else set @IsRight=0 go declare @IsRight int exec StuProc '趙雷' , @IsRight output select @IsRight以上是全局變量,下面來了解局部變量 局部變量:局部變量也稱爲內部變量。局部變量是在函數內做定義說明的。其做用域僅限於函數內部,離開該函數後再使用這種變量是非法的。局部變量的定義:必須先用Declare命令定之後纔可使用,declare{@變量名 數據類型}局部變量的賦值方法:set{@變量名=表達式}或者select{@變量名=表達式}局部變量的顯示: create proc StuProc as declare @sname varchar(100) set @sname='趙雷' select S#,Sname,Sage,Ssex from student where sname=@sname go exec StuProc 那若是是要把局部變量的數據顯示出來怎麼辦呢?create proc StuProc as declare @sname varchar(100) set @sname=(select Sname from student where S#=01) select @sname go exec StuProc 更詳細的實例操做學習好比,在SQL Server查詢編輯器窗口中用CREATE PROCEDURE語句建立存儲過程PROC_InsertEmployee,用於實現向員工信息表(tb_Employee)中添加信息,同時生成自動編號。其SQL語句以下:IF EXISTS (SELECT name FROM sysobjects WHERE name = 'Proc_InsertEmployee' AND type = 'P') DROP PROCEDURE Proc_InsertEmployee GO CREATE PROCEDURE Proc_InsertEmployee @PName nvarchar(50), @PSex nvarchar(4), @PAge int, @PWage money AS begin declare @PID nvarchar(50) select @PID=Max(員工編號) from tb_Employee if(@PID is null) set @PID='P1001' else set @PID='P' cast(cast(substring(@PID,2,4) as int) 1 as nvarchar(50)) begin insert into tb_Employee values(@PID,@PName,@PSex,@PAge,@PWage) end end go存儲過程的修改:建立完存儲過程以後,若是須要從新修改存儲過程的功能及參數,能夠在SQL Server 2005中經過如下兩種方法進行修改:一種是用Microsoft SQL Server Mangement修改存儲過程;另一種是用T-SQL語句修改存儲過程。使用Microsoft SQL Server Mangement修改存儲過程,步驟以下: (1)在SQL Server Management Studio的「對象資源管理器」中,選擇要修改存儲過程所在的數據庫(如:db_18),而後在該數據庫下,選擇「可編程性」。 (2)打開「存儲過程」文件夾,右鍵單擊要修改的存儲過程(如:PROC_SEINFO),在彈出的快捷菜單中選擇「修改」命令,將會出現查詢編輯器窗口。用戶能夠在此窗口中編輯T-SQL代碼,完成編輯後,單擊工具欄中的「執行(X)」按鈕,執行修改代碼。用戶能夠在查詢編輯器下方的Message窗口中看到執行結果信息。使用Transact-SQL修改存儲過程: 使用ALTER PROCEDURE語句修改存儲過程,它不會影響存儲過程的權限設定,也不會更改存儲過程的名稱。語法:ALTER PROC [ EDURE ] procedure_name [ ; number ] [ { @parameter data_type } [ VARYING ] [ = default ] [ OUTPUT ] ] [ ,...n ] [ WITH { RECOMPILE | ENCRYPTION | RECOMPILE , ENCRYPTION } ] [ FOR REPLICATION ] AS sql_statement [ ...n ]參數說明:procedure_name:是要更改的存儲過程的名稱。交叉連接:關於ALTER PROCEDURE語句的其餘參數與CREATE PROCEDURE語句相同,可參見上面的「建立存儲過程的參數」。例如,修改存儲過程PROC_SEINFO,用於查詢年齡大於35的員工信息。SQL語句以下: ALTER PROCEDURE [dbo].[PROC_SEINFO] AS BEGIN SELECT * FROM tb_Employee where 員工年齡>35 END 存儲過程的刪除:使用Microsoft SQL Server Mangement刪除存儲過程,步驟以下: (1)在SQL Server Management Studio的「對象資源管理器」中,選擇要刪除存儲過程所在的數據庫(如:db_student),而後在該數據庫下選擇「可編程性」。 (2)打開「存儲過程」文件夾,右鍵單擊要刪除的存儲過程(如:PROC_SEINFO),在彈出的快捷菜單中選擇「刪除」命令。(3)單擊「肯定」按鈕,便可刪除所選定的存儲過程。 注意:刪除數據表後,並不會刪除相關聯的存儲過程,只是其存儲過程沒法執行。使用T-SQL刪除存儲過程: DROP PROCEDURE語句用於從當前數據庫中刪除一個或多個存儲過程或過程組。 語法: DROP PROCEDURE { procedure } [ ,...n ] 參數說明: Procedure:是要刪除的存儲過程或存儲過程組的名稱。過程名稱必須符合標識符規則。能夠選擇是否指定過程全部者名稱,但不能指定服務器名稱和數據庫名稱。 n:是表示能夠指定多個過程的佔位符。 例如刪除PROC_SEINFO存儲過程的SQL語句以下。 DROP PROCEDURE PROC_SEINFO例如,刪除多個存儲過程proc十、proc20和proc30。DROP PROCEDURE proc10, proc20, proc30 例如,刪除存儲過程組procs(其中包含存儲過程proc一、proc二、proc3)。 DROP PROCEDURE procs注意:SQL語句DROP不能刪除存儲過程組中的單個存儲過程。 應用存儲過程驗證用戶登陸身份:目前,驗證用戶登陸身份的方法有多種,而經過調用存儲過程來實現用戶身份驗證是目前最好的解決方案之一。由於存儲過程在建立時即在服務器上進行編譯,因此執行起來比單個SQL語句要快得多。 本例是經過調用存儲過程來驗證用戶登陸的用戶名和密碼是否正確。運行本實例,在「用戶名」和「密碼」文本框中輸入相應的用戶名和密碼,單擊「登陸」按鈕便可。程序開發步驟:(1)新建一個網站,將其命名爲"index",默認主頁名爲Default.aspx。 (2)Default.aspx頁面涉及到的控件如表1所示。(3)主要程序代碼以下。打開SQL Server Management Studio,並鏈接到SQL Server2005中的數據庫。單擊工具欄中「 」按鈕,新建查詢編輯器。在該查詢編輯器中,建立驗證登陸用戶身份的存儲過程PROC_EXISTS,具體的SQL語句以下: CREATE PROC PROC_EXISTS ( @UserName NVARCHAR(20), @PassWord NVARCHAR(20), @ReturnValue int OUTPUT ) AS IF EXISTS(select * from tb_member where userName=@UserName AND passWord=@PassWord) set @ReturnValue= 100 ELSE set @ReturnValue= -100 GO 在"登陸"按鈕的Click事件下,執行驗證登陸用戶身份的存儲過程,若是輸入的用戶名和密碼正確,則彈出對話框提示用戶登陸成功,代碼以下: protected void btnLogin_Click(object sender, EventArgs e) { //鏈接數據庫 myConn = new SqlConnection(ConfigurationManager.AppSettings["ConnectionString"].ToString()); myCmd = new SqlCommand("PROC_EXISTS", myConn); //調用存儲過程,判斷用戶是否存在 myCmd.CommandType = CommandType.StoredProcedure; //爲存儲過程的參數賦值 SqlParameter userName=new SqlParameter("@UserName", SqlDbType.NVarChar, 20); userName.Value=this.txtName.Text.Trim(); myCmd.Parameters.Add(userName); SqlParameter passWord=new SqlParameter("@PassWord", SqlDbType.NVarChar, 20); passWord.Value = this.txtPassword.Text.Trim(); myCmd.Parameters.Add(passWord); //指出該參數是存儲過程的OUTPUT參數 SqlParameter ReturnValue = new SqlParameter("@ReturnValue",SqlDbType.Int ,4); ReturnValue.Direction = ParameterDirection.Output; myCmd.Parameters.Add(ReturnValue); try { myConn.Open(); myCmd.ExecuteNonQuery(); if (int.Parse(ReturnValue.Value.ToString()) == 100) { Response.Write("<script>alert('您是合法用戶,登陸成功!')</script>"); return; } else { Response.Write("<script>alert('您輸入的用戶名和密碼不正確,請從新輸入!')</script>"); return; } } catch(Exception ex) { Response.Write(ex.Message.ToString()); } finally { myConn.Close(); myConn.Dispose(); myCmd.Dispose(); }}
declare @userid varchar(8000), @serid numeric(19, 0), @index int, @tserid numeric(18, 0), @tuserid numeric(18, 0)DECLARE MyCursor CURSOR FOR SELECT userid, serid FROM MYOS_WORKFLOWTASKDESCRIPITOR where type = '0001'OPEN MyCursorFETCH NEXT FROM MyCursor into @userid, @seridWHILE @@FETCH_STATUS = 0BEGIN while ltrim(rtrim(@userid)) != '' begin set @index = charindex(',', @userid, 1) if (@index = 0) set @index = (len(@userid) 1) set @tuserid = convert(numeric(18, 0), substring(@userid, 1, @index - 1)) set @tserid = convert(numeric(18, 0), @serid) if not exists (select * from xzfw_service_user where serviceid = @tserid and userid = @tuserid) insert into xzfw_service_user (userid, serviceid) values (@tuserid, @tserid) if (@index > len(@userid)) set @userid = '' else set @userid = substring(@userid, @index 1, len(@userid) - @index) end FETCH NEXT FROM MyCursor into @userid, @seridENDCLOSE MyCursorDEALLOCATE MyCursorGO
/* 統一平臺用戶角色綁定,用戶登陸名建立 注:批量綁定角色和批量建立登陸,該腳本將全部的用戶賦予指定的應用角色權限, 並對未建立登陸的用戶自動建立。通常用於對政務應用系統批量操做,零散用戶請手工操做。 1.先在平臺的角色管理中建立一個應用的角色,並賦予相應功能權限 2.而後經過select * from [dbo].[PT_APP_ROLE] where yyid='402881f236ed5eb60136ed64285e0007' 查找到建立角色的rid值 yyid指應用系統的LID,能夠經過[dbo].[PT_COOPERATION]表查到應用的LID 3.須要對給用戶賦予哪一個應用的權限,就傳入該應用的角色ID 4.需給初始化密碼的MD5值,不要直接給密碼,是MD5碼的值。 另:須要隨機生成字符串存儲過程,生成一個22位的隨機字符串作爲OID。 */ declare @rond varchar(22) ,@roleid varchar(50) ,@userid varchar(50) ,@uid varchar(50) ,@ucode varchar(30) ,@uname varchar(50) ,@upass varchar(50); -------------------------------------------------------------------------- --------傳入變量值-------------------------------------------------------- set @roleid='402881ba48f4130b0148f414ac000009'; --傳入角色ID值 set @upass='202cb962ac59075b964b07152d234b70'; --傳入初始化密碼123 -------------------------------------------------------------------------- ------------------主體開始,角色綁定登陸建立------------------------------ declare sr cursor for select OID FROM DBO.PT_USER WHERE JGOID!='10'; open sr fetch next from sr into @userid while @@FETCH_STATUS=0 begin set @ucode='';set @uname='';set @uid=''; select @ucode=CODE,@uname=NAME from dbo.PT_USER where OID=@userid; if(select COUNT(user_id) from [dbo].[PT_APP_USER_ROLE] where user_id=@userid and role_id=@roleid)=0 begin exec RandomStr @rond output; --隨機生成22位字符串 set @uid='4028815d48' @rond; --指定前10位編碼,生成角色OID INSERT INTO [dbo].[PT_APP_USER_ROLE] ([ur_id] ,[user_id] ,[role_id]) VALUES (@uid,@userid,@roleid); end if(select COUNT(oid) from dbo.PT_LOGIN where userid=@userid)=0 begin set @uid=''; exec RandomStr @rond output; --隨機生成22位字符串 set @uid='402881ba48' @rond; --指定前10位編碼,生成登陸OID INSERT INTO [dbo].[PT_LOGIN] ([oid] , [loginid] , [loginname] , [loginpass] , [status] , [userid]) VALUES (@uid ,@ucode ,@uname ,@upass ,'0' ,@userid); end fetch next from sr into @userid; end close sr; deallocate sr; ------------------主體結束,角色綁定登陸結束------------------------------ --select * from dbo.PT_USER where JGOID!='10' --select * from dbo.PT_LOGIN ----4028815d48f4c6790148f7e2e6b800d3 --SELECT * FROM [dbo].[PT_COOPERATION] --select * from [dbo].[PT_APP_ROLE] where yyid='402881f236ed5eb60136ed64285e0007' --402881ba48f4130b0148f414ac000009 --select * from [dbo].[PT_APP_USER_ROLE] where user_id='297e009348f506030148f5326b020048'
declare @caseid varchar(50), @shoulioid varchar(50), @banjieoid varchar(50) begin set @caseid = '';--在此外輸入須要刪除的辦件編號 set @shoulioid = '';--受理id set @banjieoid = '';--辦結id print '正在刪除辦件材料,補齊補正材料,投訴,督察,預警,紅黃牌等...' delete from xzxk_case_atta where caseid=@caseid;/*刪除辦件材料*/ delete from xzxk_buqibuzheng where caseid=@caseid;/*刪除補齊補正*/ delete from xzxk_buqibuzheng_atta where caseid=@caseid;/*刪除補齊補正附件*/ --delete from xzxk_tousu_banjie where toushuoid in(select toushuoid from xzfw_tousu where caseid=@caseid);/*刪除投訴辦結*/ --delete from xzxk_tousu_shouli where toushuoid in(select toushuoid from xzfw_tousu where caseid=@caseid);/*刪除投訴受理*/ --delete from xzxk_tousu where caseid=@caseid;/*刪除投訴*/ delete from yjdc_super_content where caseid=@caseid;/*刪除督察*/ delete from yjdc_warn_content where caseid=@caseid;/*刪除預警*/ delete from yjdc_yellowred_content where caseid=@caseid;/*刪除紅黃牌*/ /*判斷是否存在窗口收件*/ if(exists (select caseid from XZXK_SHOUJIAN where caseid=@caseid)) begin print '正在刪除窗口收件...'; delete from XZXK_SHOUJIAN where caseid=@caseid; end; /*判斷是否存在網絡收件*/ --if(exists (select shouli_number from net_case where shouli_number=@caseid)) --begin -- print '正在刪除網絡收件...' -- delete from net_case where shouli_number=@caseid; --end; /*判斷是否存在受理*/ if(exists (select shoulioid from XZXK_SHOULI where caseid=@caseid)) begin set @shoulioid=(select shoulioid from XZXK_SHOULI where caseid=@caseid); print '正在刪除審批,特別程序,掛起,收費,催辦,證實日誌,工做流任務...'; delete from XZXK_SHENPI where shoulioid=@shoulioid;/*刪除審批數據*/ delete from XZXK_TeShuChengXu where shoulioid=@shoulioid;/*刪除特別程序*/ delete from XZXK_CASE_PAUSE where shoulioid=@shoulioid;/*刪除掛起*/ delete from XZXK_PRICEDETAIL where shoulioid=@shoulioid;/*刪除收費*/ delete from XZXK_CUIBAN where shouli_oid=@shoulioid;/*刪除催辦*/ --delete from zhengzhaolog where shoulioid=@shoulioid;/*刪除證照日誌*/ delete from myos_workflowtask where taskid=@shoulioid;/*刪除工做流任務*/ /*判斷是否存在辦結*/ if(exists (select banjieoid from XZXK_BANJIE where shoulioid=@shoulioid)) begin print '正在刪除辦結...'; set @banjieoid=(select banjieoid from XZXK_BANJIE where shoulioid=@shoulioid); delete from XZXK_BANJIE_ATTA where banjieoid=@banjieoid;/*刪除辦結附件*/ delete from XZXK_BANJIE where banjieoid=@banjieoid;/*刪除辦結*/ end; print '正在刪除受理...' delete from XZXK_SHOULI where shoulioid=@shoulioid;/*刪除受理*/ end; end
SQL server查看語句響應狀況 做者:李永 發佈時間:2018-11-22 14:39 SELECT TOP 1000 ST.text AS '執行的SQL語句', QS.execution_count AS '執行次數', QS.total_elapsed_time AS '耗時', QS.total_logical_reads AS '邏輯讀取次數', QS.total_logical_writes AS '邏輯寫入次數', QS.total_physical_reads AS '物理讀取次數', QS.creation_time AS '執行時間' , QS.* FROM sys.dm_exec_query_stats QS CROSS APPLY sys.dm_exec_sql_text(QS.sql_handle) ST WHERE QS.creation_time BETWEEN '2015-08-01 00:00:00' AND '2015-09-02 11:00:00' ORDER BY QS.total_elapsed_time DESC