# MSSQL tsql stored procedure 預存程序和函式 常用語法筆記 (暫存表、宣告變數、if條件式) ## 簡介 預存程序(stored procedure) 是在資料庫預先擺放程式碼,以便外部程式呼叫時,可以在資料庫端先做運算,運算後再取出資料。這樣的作法有一個不可取代的好處,如果原本要運算的資料量很大,但經過運算後可以只要一點點結果,那就可以利用預存程序先行運算把資料減少,這樣傳輸到外部程式消耗的頻寬也會變少。 ## 將查詢到的結果寫入暫存資料表 temptable ```sql= SELECT * INTO #temptable FROM TestTable -- 複製Table的結構至#temptable SELECT * FROM #temptable --- 取出資料 DROP TABLE #temptable --- 刪除暫存的資料表 ``` ## 查詢到的結果寫入暫存資料表 temptable,同時附帶 join、 where 等條件參數 這個範例是只取 Left join 左側並且排除中間重疊部分的語法,見下圖 ![](https://hackmd.io/_uploads/HJl_oMJvIh.png) ```sql= SELECT [ID],[Name] INTO #temptable FROM [MyTable1] LEFT JOIN [MyTable1] ON [MyTable1].[ID] = [MyTable2].[ID] WHERE [MyTable2].[ID] IS NULL; ``` 更多 join 類的經典範例請見 [Visual Representation of SQL Joins](https://www.codeproject.com/Articles/33052/Visual-Representation-of-SQL-Joins) [![](https://hackmd.io/_uploads/SysD7JwUh.png)](https://hackmd.io/_uploads/SysD7JwUh.png) --- ## 暫存資料表 temptable 前面的符號有分成 # ## @ 三種分別是什麼意思? 前面提到 DROP TABLE #temptable ,是刪除暫存的資料表,#和@符號分別代表存位置不同 * 一個#和兩個##,只要有# 符號,資料就是存在硬碟,與資料庫連線session中斷時會刪除,也可以自己手動下drop刪除 * 兩個 # 的 ##Table 是全域的資料表,跨資料庫也可以讀取資料 * 一個@ 資料存在記憶體,指令執行結束就會自動刪除,不需手動drop ## 預存程序、資料表值函式、純量值函式差別 預存程序不一定要回傳結果 (可能只是在資料庫動態新增資料) 資料表值函式和純量值函式一定會回傳結果,只是差在回傳一個table還是一個變數而已 ### 呼叫預存程序的方式是 ```=sql exec 預存程序名稱 @變數名稱1 ='變數內容1',@變數名稱2 ='變數內容2' ``` 實際用起來像這樣 ```=sql exec dbo.SearchHtml @SearchString ='%關鍵字%',@Category = 2 ``` ### 呼叫資料表值函式 這邊就跟預存程序不一樣了,因為是**資料表**的概念,所以直接用 select 即可 ```=sql select* from 資料表值函式名稱('變數','變數') ``` ## 建立預存程序 預存程序 PROCEDURE (Stored procedure) 不需要宣告回傳的型態,可以有回傳執行結果,也可以是單純insert不做回傳,宣告方式如下 ```=sql CREATE PROCEDURE 預存程序名稱 -- 可以傳入的變數定義寫在這裡 @SearchString nvarchar(MAX) AS BEGIN -- SET NOCOUNT ON added to prevent extra result sets from -- interfering with SELECT statements. SET NOCOUNT ON; SELECT * FROM table END ``` ## 建立資料表值函式、純量值函式 這兩個函式都一定會有回傳值,所以 Create 完,下面有一個 RETURNS 要寫回傳的型態,資料表值函式就是回傳一個TABLE(類似普通sql語法查詢結果),純量值函式則是特定一個變數,可以是字串也可以是數值 ```=sql CREATE FUNCTION 函式名稱 ( -- 可以傳入的變數定義寫在這裡 @變數名稱 變數型態 ) RETURNS NVARCHAR(MAX) AS BEGIN END ``` 範例 ```=sql CREATE FUNCTION [dbo].[GetTreeNodeUnitName] ( -- 可以傳入的變數定義寫在這裡 @NowPage int, @UserName NVARCHAR(20) ) RETURNS NVARCHAR(MAX) AS BEGIN select @UnitName = a.UserName from table a where a.User = @UserName and a.Page > @NowPage END ``` --- ## 宣告變數 DECLARE 格式是 ```=sql DECLARE @變數名稱 變數型態(參數) ``` 例如 ```=sql DECLARE @UserName VARCHAR(30); --宣告變數名稱UserName,型態為字串,長度30 ``` ## 常見的變數型態 ```=sql DECLARE @SqlVariable NCHAR(4); --固定長度4 DECLARE @SqlVariable NVARCHAR(50); --變動長度50 DECLARE @SqlVariable NVARCHAR(MAX); --長度設 max 可存到 2GB (同 text/ntext 的長度) DECLARE @SqlVariable INT; --整數 DECLARE @SqlVariable decimal(5,2); --總長度5位數,小數點以後佔2位,如123.45 DECLARE @SqlVariable datetime; --日期時間 DECLARE @SqlVariable UNIQUEIDENTIFIER; ``` UNIQUEIDENTIFIER 就是C#的 GUID,格式會是這樣 xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx ,其中每一個 x 是範圍 0-9 或 a-f 的十六進位數字。 例如,6F9619FF-8B86-D011-B42D-00C04FC964FF。 --- ## 使用if else條件判斷式 僅節錄片段,詳細可參考 這篇文章 [[SQL] 使用 Stored Procedure 動態組成 SQL 查詢指令](https://dotblogs.com.tw/johnny/2010/01/25/13291) ```=sql CREATE PROCEDURE dbo.QueryProduct ( @ProductID smallint ) AS --設定三組sql變數 DECLARE @statement nvarchar(256) DECLARE @orderby nvarchar(40) DECLARE @where nvarchar(256) --給予變數初始值 SET @statement = 'SELECT [ProductID] FROM Table' SET @orderby = ' ORDER BY [ProductID] ' /*------- WHERE 的 if 範例 -------------- */ IF (@ProductID IS NULL) BEGIN SET @where = ' WHERE 1 = 1 ' END ELSE BEGIN --如果資料庫的ProductID是int的話就不用在這邊使用CAST轉型了 SET @where = ' WHERE [ProductID] = ' + CAST(@ProductID AS varchar) END -- 組合字串 SET @statement = @statement + @where + @orderby PRINT 'STATEMENT: ' + @statement EXEC sp_executesql @statement RETURN ``` --- ## 參考來源 執行預存程序 https://docs.microsoft.com/zh-tw/sql/relational-databases/stored-procedures/execute-a-stored-procedure?view=sql-server-ver15 datetime (Transact-SQL) https://docs.microsoft.com/zh-tw/sql/t-sql/data-types/datetime-transact-sql?view=sql-server-ver15 #TEMPTABLE 、##TEMPTABLE 、@TEMPTABLE 區別?! https://dotblogs.com.tw/hellouk/2010/10/07/18163 SQL - Temp Table 小技巧 https://dotblogs.com.tw/justforgood/2014/02/20/144091 [iT鐵人賽Day6]SQL Server 資料型態 char varchar nchar nvarchar https://ithelp.ithome.com.tw/articles/10213922 [SQL] 使用 Stored Procedure 動態組成 SQL 查詢指令 https://dotblogs.com.tw/johnny/2010/01/25/13291 --- ###### tags: `資料庫`