對於SQL Server,我是個拿來主義。不少底層的原理並不瞭解,就直接模仿拿着來用了,到了報錯的時候,纔去找緣由進而逐步深刻底層。我想,是每一次的報錯,逼着我一點點進步的吧。sql
近期因爲項目的緣由,我須要寫一些存儲過程。同時學校還開了一門《數據庫系統》的課程。二者結合知足了我濃厚的興趣。數據庫
下面寫寫我對存儲過程的簡單認識。編程
首先聲明:初學者最好看一些參考書,有些規範什麼的,我並無遵照,中間可能有一些很差的習慣,或者一些不太注重的細節,好比變量的命名等,請提出指正。c#
1、基礎知識:架構
1.select,insert,update,delete 的語法 ,這是核心中的核心框架
2.一點點的T-SQL編程基礎:瞭解基本的過程流,如if...else,wihle ,for ;變量的賦值,變量類型,簡單函數等等編程語言
可能你們對sq語句最熟悉,那從sql首先通過T-SQL編程,再進化到存儲過程。ide
存儲過程的優勢: 函數
2、實例:(可觀察存儲過程與其餘編程語言異同,而後看下面的基本語法,着重看二者的不一樣之處) 測試
--創建測試數據庫
CREATE DATABASE Test
go
--創建測試表
USE Test
CREATE TABLE t2 ([Item_Code] [varchar](500) NULL,[Item_FileName] [varchar](500) NULL);
--帶輸入參數和控制流程語句的存儲過程 CREATE PROCEDURE [dbo].[ProcT] (@code_name varchar(50)) AS BEGIN insert into t2 ([Item_Code],[Item_FileName]) values('1','測試1'),('2','測試2'),('3','測試3'),('4','測試4'); if @code_name='1' begin select '請從新輸入' as warning; end else begin select [Item_Code] ,[Item_FileName] from t2 where Item_Code like '%'+@code_name+'%'; end END --執行存儲過程 exec [ProcT] @code_name='1'
結果:
--執行存儲過程 exec [TansProc] @code_name='2'
結果:
--刪除存儲過程 drop PROCEDURE TansProc
3、我理解的基本語法:
首先,我對存儲過程的理解就是把sql 語句封裝起來,存起來,等到須要的的時候只要執行存錯過程的名稱就行了。
最簡單的一個例子,就是
use CrawlData --代表在哪一個數據庫裏面建立存儲過程 go create proc dbo.ProcTest --其中proc爲 procedure的縮寫,SQL Sever中,一些長的命令如execute 可簡寫前面的4個字母爲exec; --dbo爲架構名; --ProcTest爲存儲過程的名稱,通常以Proc命名較容易識別這建立的對象爲存儲過程,不要以sp_爲前綴,由於sp_通常爲系統函數 as --as 爲關鍵字 print '我是好人'; --一個輸出 go
第二部分:常識(其實越簡單的越容易被忽略,這些常識我以前幾乎沒有重視過,可是他們真的很重要):
1.go爲批處理分隔符關鍵字,必須爲這一行的惟一關鍵字
除此以外,他還能夠用來屢次提交批處理,例如:這個可輸出5次'It is funny'
PRINT 'It is funny' go 5
2.語句終止用「;」,雖然有時不用也不影響結果,最好仍是養成習慣用
3.關鍵字不區分大小寫,例如EXEC 和 exec是一個做用
4.參數直接在存儲過程名後面聲明,前面均有@,後指明參數的類型如int,char,varchar等等
5.begin,end經常用在一個過程流的開始和結束,不然該判斷將失效。例如 if @t=1 begin select @t end ,若是不加,則select @t將會被順序執行,判斷「 if @t=1」失效
6.use database_name,在執行存儲過程或sql語句事,要麼適用use 來定位到相應的數據庫,要麼在圖形化界面中先選好。
我通常事先選好,因此use命令較少用。當需跨數據庫查詢時,可在查詢的表格前加上數據庫名,例如 insert into databaseB.[dbo].tableB (b) select a from databaseA.[dbo].tableA
第三部分:基本命令(常常用到的):
1.set命令,主要用於從表達式中賦值,例如 declare @T VARCHAR(10) set @T='5',這是與其它編程語言的不一樣之處。
2.select命令,它神通廣大,做用很是多。其一,能夠從數據源中檢索數據賦值,例如 select @T=Item_Code from t2 where Item_FileName='測試2' ;其二能夠輸出變量的值,例如 select @T;
二者的相同之處是均可以把表達式的值複製給變量,當select從數據源的賦值時,若其後無WHERE條件子句的限制,一次查出了多條語句,此時,會將查詢到的最後一條語句中相應的值賦值給變量。
3.alter,drop對存儲過程也一樣適用,例如修改存儲過程,則alter ProcTest as select @T。而刪除存儲過程,則drop proc ProcTest
第四部分:數據傳遞
1.輸入參數
有兩種方式在存儲過程執行期間傳遞參數值:命名參數和位置參數。例如exec ProcT @code_name='2'爲命名參數傳遞;而exec ProcT '2'爲位置參數傳遞,位置參數無須指定變量名,按照聲明參數時的參數位置來傳遞。
當聲明的變量較多時,通常命名參數較好。聲明參數較少時,用位置參數便可。
調用存儲過程時,必須給輸入參數賦值,除非參數有默認值。
2.提供列表和表做爲存儲過程的輸入參數
(1) 動態的構造T-SQL,先聲明一個nvarchar類型的變量存一個sql語句,而後用函數sp_executesql執行。例如:
use Test; go create proc dbo.ProcSearch @code varchar(10) as Declare @SQLString nvarchar(1000) set @SQLString=N'SELECT Item_code,Item_filename from t2 where Item_code in ('+@code+');' exec sp_executesql @SQLString go exec ProcSearch @code='1,2,4'
結果:

(2)以XML格式傳遞列表,使用sp_xml_preparedocument準備XML文檔,而後用OPENXML函數將XML文檔的內容插入內部變量。這部分須要先了解下XSD,即xml的框架定義語言。這裏只是稍微說起,之後用到這部分的時候再詳細研究。
(3)提供表做爲輸入參數
將表值參數做爲輸入參數傳入存儲過程,必須首先將表值參數定義爲用戶定義的表類型。
在建立儲存過程期間將用戶定義的表類型指定爲輸入參數後,必須將表類型定位爲READONLY
--第一步 :建立用戶定義的表類型 create type t2Type1 as table (item_code varchar(500),item_filename varchar (500)) ; --第二步:定義存儲過程,使用第一步的類型做爲輸入參數的數據類型 alter proc ProcT3 (@CodeTable [dbo].t2Type1 readonly) as select a.item_filename,b.item_filename from t2 as a join @CodeTable as b on a.item_code=b.item_code --第三步:執行該存儲過程 --須要先聲明一個表值參數,而後填充該參數的值 declare @Ctable as t2Type1 insert into @Ctable (item_code,item_filename) values('4','TEST4'); --執行 EXEC ProcT3 @CodeTable=@Ctable
結果:
3.從存儲過程當中返回數據
返回單個結果:
create proc ProT4 @countALL INT OUTPUT --輸出參數聲明時加 output關鍵字 AS SELECT @countALL=COUNT(*) FROM t2 declare @AC int ;--聲明接收輸出參數的局部變量 exec ProT4 @countALL=@AC OUTPUT --執行時也需加 output關鍵字 SELECT @AC --輸出參數值
返回結果集:(有兩種方式,第一種最簡單的就是直接返回查詢的表;第二種是用WITH RESULT SETS來從新定義輸出列名和數據類型,此特性只在2012版或以上的版本支持)
create proc ProT5 as SELECT [Item_Code],item_filename FROM t2 EXEC ProT5 with RESULT sets (([Code] varchar(10),filename varchar(10))) --見結果ProT5-1
EXEC ProT5 --見結果ProT5-2
結果ProT5-1
結果ProT5-2
除此以外還可用INSERT...EXECUTER與永久表,表變量,或臨時表結合使用
例如 insert t2 exec ProT5 ,至關於把t2的數據翻倍,固然舉的這個例子,不是很恰當,可是在其餘時候,咱們就能夠模仿此種思路來轉移表
4、概念辨析:
5、c#調用存儲過程
參考資料:
1.存儲過程詳解:https://msdn.microsoft.com/zh-CN/library/ms345415(v=sql.120).aspx
2.張慧娟(譯).SQL Server 2012 寶典(第四版).清華大學出版社.2014.5:第295-343頁,第IV部分:使用T-SQL編程
3. 表值參數問題:https://msdn.microsoft.com/zh-cn/library/bb675163.aspx