T-SQL基礎(六)之可程式設計物件
-- 宣告變數 DECLARE @variable_name [AS] variable_type; -- 變數賦值 SET @variable_name = variable_value;
示例如下:
DECLARE @age INT; -- SET一次只能操作一個變數 SET @age = 26;
T-SQL提供了使用SELECT語句來給變數賦值的擴充套件功能:
SELECT @age = 30;
也可以使用子查詢來給變數賦值:
USE WJChi; SET @age = ( SELECT Age FROMdbo.UserInfo WHERE Name = '雪飛鴻' );
注意,上述SET語句中的子查詢必須只能返回標量,否則會報錯,示例如下:
USE WJChi; SET @age = ( SELECT Age FROM dbo.UserInfo );
執行報錯:
子查詢返回的值不止一個。當子查詢跟隨在 =、!=、<、<=、>、>= 之後,或子查詢用作表示式時,這種情況是不允許的。
批
批是一條或多條被客戶端作為整體傳送給SQL Server進行執行的T-SQL語句,SQL Server以GO命令來標識一個批的結束,注意,GO語句不能使用分號結尾
批是一個解析單元,因此,即便在同一個批中修改了表結構,然後執行增刪改查操作會引發解析錯誤,因為在同一批中的增刪改查語句並不知道表結構已發生了變化。
GO n:表示執行n次批中的語句,如:
USE WJChi; SELECT * FROM dbo.UserInfo; GO 5
流程控制
IF...ELSE...
句式結構如下:
IF condition BEGIN --do something END ELSE IF condition BEGIN -- do something END ELSE BEGIN -- do something END;
IF...ELSE...支援巢狀
WHILE
句式結構如下:
WHILE condition BEGIN -- do something END;
TRY...CATCH... & 錯誤處理
句式結構如下:
BEGIN TRY -- do something END TRY BEGIN CATCH -- do something END CATCH;
SQL Server提供了一組描述錯誤的函式:
函式 | 作用 |
---|---|
ERROR_NUMBER() | 獲取錯誤編號 |
ERROR_MESSAGE() | 獲取錯誤的文字資訊 |
ERROR_SEVERITY() | 獲取錯誤嚴重級別 |
ERROR_STATE() | 獲取錯誤狀態 |
ERROR_LINE() | 獲取錯誤發生行號 |
ERROR_PROCEDURE() | 獲取錯誤發生的過程名 |
也可以通過語句:
SELECT * FROM sys.messages;
來獲取錯誤相關資訊。可以使用THROW語句來丟擲錯誤。
其它
RETURN、CONTINUE、BREAK、WAITFOR、GOTO
更多詳細內容,參考微軟官方文件:Control-of-Flow
臨時表
SQL Server支援三種臨時表:本地臨時表、全域性臨時表和表變數。這三種臨時表建立後都儲存在tempdb資料庫中。
本地臨時表
建立本地臨時表的方式不普通的資料表相同,但本地臨時表僅在它被建立的會話中可見,會話結束後,臨時表也會被銷燬。
臨時表以#開頭,如:#UserInfo
。臨時表中的資料儲存在磁碟中。
全域性臨時表
與本地臨時表最大的不同是:全域性臨時表對所有會話可見,當全域性臨時表不在被任何會話引用時,會被SQL Server銷燬。
全域性臨時表以##開頭,如:##UserInfo
。
可通過語句:
SELECT * FROM tempdb..sysobjects WHERE name LIKE '%temp%'
來檢視建立的臨時表資訊:
表變數
表變數的宣告與普通變數類似,使用DECLARE語句。表變數只在建立它的會話中可見,且只對當前批可見。
一個顯式事務回滾,事務中對臨時表的修改也會回滾,但對已完成的表變數修改,則不會回滾。資料量較少時建議使用表變數,資料量較大時推薦使用臨時表。
表變數 vs 臨時表
表變數與臨時表類似,但二者有所區別。臨時表更多的強調它是資料表,表變數著重點則在於變數上。
表型別
當建立了表型別,就會在資料庫中保留表的定義,可以複用它建立表變數,也可作為儲存過程和自定義函式的輸入引數。
CREATE TYPE TableType AS TABLE ( Id INT PRIMARY KEY ); DECLARE @t TableType;
DROP TYPE TableType;
點選此處,檢視有關型別的更多內容。
動態執行SQL
SQL Server中可以使用兩種方式來執行動態SQL:EXEC命令與sql_executesql儲存過程。
EXEC
EXEC是T-SQL提供的執行動態SQL的原始技術,接收一個字串作為輸入並執行字串中的語句:
USE WJChi; EXEC('SELECT * FROM dbo.UAddress');
EXEC支援正則與Unicode字元作為輸入。
sql_executesql
sql_executesql儲存過程在EXEC命令之後引入,與EXEC相比,sql_executesql更安全,更靈活,可以支援輸入與輸出引數。但,sql_executesql只支援Unicode字元作為輸入。
ADO.NET傳送到SQL Server的引數化查詢語句就是使用sql_executesql來執行的,引數化查詢可以有效避免SQL注入攻擊。示例如下:
exec sp_executesql N'SELECT * FROM dbo.UAddress WHERE [email protected] AND [email protected]',N'@sd nvarchar(4000),@ld nvarchar(4000)',@sd=N'河南省',@ld=N'河南省鄭州市'
函式 & 儲存過程 & 觸發器
函式
建立函式的CREATE FUNCTION
語句必須是當前批中的第一條語句,否則報錯:'CREATE FUNCTION' 必須是查詢批次中的第一個語句。
建立標量值函式:
CREATE FUNCTION dbo.GetSum ( @left AS INT, @right AS INT ) RETURNS INT AS BEGIN RETURN @left+@right; END;
建立表值函式:
CREATE FUNCTION dbo.TableFunc ( @name AS VARCHAR(8) ) RETURNS TABLE AS RETURN ( SELECT * FROM dbo.UserInfo WHERE Name = @name );
修改函式定義,將建立函式語句中的CREATE換為ALTER即可。如下所示:
ALTER FUNCTION [dbo].[TableFunc] ( @name AS VARCHAR(8) ) RETURNS TABLE AS RETURN ( SELECT * FROM dbo.UserInfo WHERE Name=@name );
刪除函式:
DROP FUNCTION function_name;
儲存過程
儲存過程與函式有相似之處,如都體現了封裝的思想,但儲存過程可以執行更為複雜的邏輯,可以有多個返回值。建立儲存過程語句如下:
CREATE PROCEDURE HumanResources.uspGetEmployeesTest2 @LastName nvarchar(50), @FirstName nvarchar(50) AS SET NOCOUNT ON; SELECT FirstName, LastName, Department FROM HumanResources.vEmployeeDepartmentHistory WHERE FirstName = @FirstName AND LastName = @LastName AND EndDate IS NULL; GO
更多詳細內容,請參閱:儲存過程(資料庫引擎)
⚠️儲存過程移植比較困難
觸發器
觸發器是特殊的儲存過程,在滿足條件時(事件被觸發),會隱式執行,從這個角度講,觸發器會增加複雜性。
觸發器個人接觸和使用較少,這裡不多介紹。詳細內容可參考:CREATE TRIGGER (Transact-SQL)
小結
本章內容較為雜亂,但也都是平時編寫T-SQL程式碼時較為常用的內容。
推薦閱讀