2013年11月24日 星期日

What's T-SQL

市面上有著許許多多的DB工具,筆著除了玩過MySQL,再來就是因工作而接觸的MS-SQL。當然,想要管理與操作,就一定要懂各家專屬的命令語法。筆著來小小道一下T-SQL特性和基本結構,透過官方和網路上許多前輩分享的,再加上我的經驗與匯整,集結出來的一些資訊,讓網友們能更了解它的面貌。

Transact-SQL(又稱T-SQL),是在Microsoft SQL Server和Sybase SQL Server上的ANSI SQL實作,與Oracle的PL/SQL性質相近(不只是實作ANSI SQL,也為自身資料庫系統的特性提供實作支援),目前在Microsoft SQL Server[1]和Sybase Adaptive Server[2]中仍然被使用為核心的查詢語言。
Transact-SQL是具有批次(Batch)與區塊特性(Block)的SQL指令集合,資料庫開發人員可以利用它來撰寫資料部份的商業邏輯(Data-based Business Logic),以強制限制前端應用程式對資料的控制能力。同時,它也是資料庫物件的主要開發語言。

-批次-

批次是指從應用程式同時傳送到 SQL Server 執行的一或多個 Transact-SQL 陳述式群組。

SQL Server 將批次的陳述式編譯成單一可執行單元,稱為執行計畫。然後一次執行完畢該執行計畫中的陳述式。

Transact-SQL 陳述式應該使用分號終止。

這不是強制性的需求,但是會取代不使用分號結束陳述式的功能,而且在未來版本的 Microsoft SQL Server 中可能會移除這個功能。

編譯錯誤 (例如語法錯誤) 會妨礙執行計畫的編譯。因此,不會執行批次中的任何陳述式。

--

執行階段錯誤會有下列其中一種影響:

1. 大部分的執行階段錯誤會停止目前的陳述式和批次中隨後進行的陳述式。
2. 某些執行階段錯誤 (像是強制違規) 只會停止目前的陳述式。批次中所有剩餘的陳述式都會執行。

在發生執行階段錯誤的陳述式之前執行的陳述式不受影響。
唯一的例外是如果批次在交易中,而該錯誤造成交易回復。

在這種情況下,執行階段錯誤回復之前所做的任何未認可的資料修改都會回復。

例如,假設某個批次中有 10 個陳述式。如果第五個陳述式有語法錯誤,批次中的所有陳述式都不會執行。

如果此批次已經完成編譯,但在執行第二個陳述式時失敗,因為第一個陳述式已經執行,所以其結果不受影響。

SQL Server 提供陳述式層級重新編譯。


也就是說,如果陳述式觸發重新編譯,則只有該陳述式會重新編譯,而非整個批次。此行為與 SQL Server 2000 不同。

例如:
Transact-SQL可以使用分號";"來分割不同的SQL指令。

INSERT INTO myTable (myText) VALUES (@myText); SELECT @IDENTITY

-區塊特性-


就如同程式裡的函數,運用BEGIN/END指令可以將多個T-SQL指令群組成一個邏輯區塊,在T-SQL通常是搭配流程控制指令來使用。一般來說,BEGIN/END指令的使用時機。


WHILE迴圈指令需要包含一個邏輯區塊的T-SQL指令。IF或ELSE條件指令需要包含一個邏輯區塊的T-SQL指令。CASE函數需要包含一個邏輯區塊的T-SQL指令。


BEGIN
{
    sql_statement | statement_block
}
END

簡單的說,當流程控制指令需要執行兩個或以上的T-SQL指令時,我們就需要使用BEGIN/END指令將它們括起來。如下所示:

IF @dbName = '金流系統'
BEGIN
   PRINT 'Database: CashFlow'
   PRINT 'Tables: Receipt, Expenditure'


END

BEGIN/END指令的使用時機,如下所示:
WHILE迴圈指令需要包含一個邏輯區塊的T-SQL指令。
IF或ELSE條件指令需要包含一個邏輯區塊的T-SQL指令。
CASE函數需要包含一個邏輯區塊的T-SQL指令。


-結構-


T-SQL指令碼大部分是一列指令敘述接著一列指令敘述循序的執行,但是對於複雜的工作,為了達成預期的執行結果,我們需要使用「流程控制結構」(Control Structures)來控制執行的流程。
T-SQL流程控制指令可以配合條件判斷來執行不同的指令敘述,或重複執行指令敘述。流程控制主要分為兩類,如下所示:
條件控制:條件控制是一個選擇題,可能為單一選擇或多選一,依照條件決定執行那一個指令敘述,或整個區塊的指令敘述。
迴圈控制:迴圈控制是重複執行指令敘述或整個區塊的指令敘述,擁有結束條件來結束迴圈執行。



Transact-SQL可支援下列的控制流程語法(control-flow):BEGIN ... END,標示SQL指令區塊,使用BEGIN ... END包裝的指令會被視為同一個指令區塊。


  1. IF ... ELSE的條件式,並可支援巢狀式的IF判斷式,若IF或ELSE中的指令包含兩個以上,則必須要使用BEGIN ... END來標示區塊,否則會發生語法檢查錯誤。
  2. WHILE迴圈,這也是Transact-SQL中唯一支援的迴圈,迴圈中的指令要用BEGIN...END包裝。
  3. RETURN,可強制終止區塊的執行。
  4. WAITFOR,可強制讓陳述式等待指定時間後才繼續執行。
  5. GOTO,可導向執行指令到指定的位置。
  6. CASE,執行單一值相等的比較。


IF條件控制指令可以依條件決定是否執行T-SQL指令敘述,如下所示:

IF 條件運算式
   { 指令敘述 | BEGIN END }
ELSE

   { 指令敘述 | BEGIN  END }

T-SQL語言的WHILE迴圈指令可以建立迴圈的控制結構,不只如此,對於WHILE迴圈,我們還可以使用BREAK指令跳出迴圈,或CONTINUE指令繼續迴圈的執行。
WHILE迴圈控制指令是在迴圈開頭檢查條件,開頭檢查可以判斷是否允許進入迴圈,只有當測試條件成立時才允許進入迴圈,不成立就離開迴圈,如下所示:

WHILE 條件運算式
   { 指令敘述 | BEGIN END }

RETURN指令可以中斷批次或預存程序的執行,也就是說,在此指令之後的指令敘述都不會執行,其基本語法如下所示:
RETURN [整數運算式]
上述語法的RETURN指令如果使用在預存程序,可以傳回一個整數值,如果沒有指定,預設傳回0。

CASE函數是執行單一值相等的比較,如下所示:

CASE 輸入運算式
   WHEN 比對運算式 THEN 結果運算式 […n]
   [ ELSE 例外的結果運算式 ]
END

WAITFOR指令可以暫停批次、預存程序或交易的執行,如下所示:

WAITFOR { DELAY | TIME } 時間

上述語法可以使用DELAY關鍵字來指定延遲一段時間,例如:2秒,或使用TIME關鍵字指定延遲至指定的時間,例如:下午10點。時間格式是hh:mm:ss。


GOTO指令可以變更執行流程至指定的標籤(Label),如下所示:

GOTO 標籤名稱

上述語法可以跳躍至標籤名稱的下一個指令敘述來繼續的執行。標籤的基本語法如下所示:
標籤名稱:

上述語言在標籤名稱後是一個「:」符號。GOTO指令最常見的應用是跳出巢狀迴圈,因為BREAK指令只能跳出目前這一層WHILE迴圈,如果需要跳出整個巢狀迴圈,就需要使用GOTO指令。


-自訂變數-

在Transact-SQL中,可以利用DECLARE來宣告變數,用SET來設定變數值,用SELECT @var = column的方式,由一個陳述式的回傳值中來取得變數值。

DECLARE @v INT -- 定義變數
SET @v = 50 -- 給予變數的值
SELECT @v = SUM(Qty) FROM SaleItemRecords WHERE SaleID = 53928 -- 從結果給予的變數

-錯誤處理-

Transact-SQL可以在區塊中使用下列方式來處理或引發錯誤:RAISERROR,擲出自訂的錯誤狀況。TRY ... CATCH,使用結構化的方式來處理錯誤(只有Microsoft SQL Server實作的Transact-SQL支援)。


-雲遊山水為知已逍遙一生而忘齡- 電腦神手

沒有留言:

張貼留言