1. 程式人生 > >T-SQL基礎(六)之可程式設計物件

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 FROM
dbo.UserInfo WHERE Name = '雪飛鴻' );

注意,上述SET語句中的子查詢必須只能返回標量,否則會報錯,示例如下:

USE WJChi;
​
SET @age =
(
    SELECT Age FROM dbo.UserInfo
);

執行報錯:

子查詢返回的值不止一個。當子查詢跟隨在 =、!=、<、<=、>、>= 之後,或子查詢用作表示式時,這種情況是不允許的。

批是一條或多條被客戶端作為整體傳送給SQL Server進行執行的T-SQL語句,SQL Server以GO命令來標識一個批的結束,注意,GO語句不能使用分號結尾

。SQL Server以批為單位進行詞法、語法分析及語句執行等工作。一個批中的錯誤不會影響另一個批中語句的執行,因為不同的批在邏輯上彼此獨立,不同批中包含的語句互相獨立,彼此互不影響

批是一個解析單元,因此,即便在同一個批中修改了表結構,然後執行增刪改查操作會引發解析錯誤,因為在同一批中的增刪改查語句並不知道表結構已發生了變化。

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'河南省鄭州市'

函式 & 儲存過程 & 觸發器

函式

使用函式的目的在於計算邏輯的封裝及程式碼的複用。SQL Server中函式返回值分為:標量與表值兩種。

建立函式的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;

SQL Server內建常用函式

儲存過程

儲存過程與函式有相似之處,如都體現了封裝的思想,但儲存過程可以執行更為複雜的邏輯,可以有多個返回值。建立儲存過程語句如下:

CREATE PROCEDURE HumanResources.uspGetEmployeesTest2   
    @LastName nvarchar(50),   
    @FirstName nvarchar(50)   
ASSET 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程式碼時較為常用的內容。

推薦閱讀

Control-of-Flow

儲存過程與函式的區別

儲存過程(資料庫引擎)

CREATE TYPE (Transact-SQL)