順序語(yǔ)句
①set語(yǔ)句
??set語(yǔ)句有兩種用法瞬矩,除了用于給局部變量賦值姑廉,還可以設(shè)定用戶執(zhí)行T-SQL命令時(shí)SQL Server的處理選項(xiàng)饭望,一般有以下幾種設(shè)定方式讨阻。
- set 選項(xiàng) on:選項(xiàng)開(kāi)關(guān)打開(kāi)芥永。
- set 選項(xiàng) off:選項(xiàng)開(kāi)關(guān)關(guān)閉。
- set 選項(xiàng)值:設(shè)定選項(xiàng)的具體值
例如钝吮,設(shè)置顯示/隱藏受T-SQL語(yǔ)句影響的行數(shù)消息語(yǔ)句埋涧,其語(yǔ)法如下:
set nocount(on|off)
②select輸出語(yǔ)句和print輸出語(yǔ)句
??SQL Server使用print或select輸出信息。
??select作為輸出使用時(shí)的語(yǔ)法如下:
select 表達(dá)式1[,表達(dá)式2,...,表達(dá)式n]
print用于向屏幕輸出信息奇瘦,其語(yǔ)法如下:
print 表達(dá)式
- select輸出會(huì)包含分隔線
- print輸出類型一定要是字符類型
【示例】
1> print 'Hello World!'
2> go
Hello World!
1> select 'Hello World!'
2> go
------------
Hello World!
分支語(yǔ)句
①IF...ELSE語(yǔ)句
IF Boolean_expression
{ sql_statement | statement_block }
[ELSE
{ sql_statement | statement_block } ]
說(shuō)明:
- IF...ELSE語(yǔ)句間不只包含一條語(yǔ)句時(shí)棘催,必須使用BEGIN...END包含多條語(yǔ)句的語(yǔ)句塊。
- 語(yǔ)句塊的關(guān)鍵字BEGIN耳标、END必須成對(duì)出現(xiàn)醇坝,允許嵌套,并且BEGIN...END之間至少包含一條SQL語(yǔ)句。
- IF...ELSE可以嵌套使用
【示例】
DECLARE @Number int;
SET @Number = 50;
IF @Number > 100
PRINT 'The number is large.';
ELSE
BEGIN
IF @Number < 10
PRINT 'The number is small.';
ELSE
PRINT 'The number is medium.';
END ;
GO
②CASE函數(shù)
??CASE是計(jì)算條件列表呼猪,并返回多個(gè)可能的結(jié)果表達(dá)式之一画畅。
??CASE 表達(dá)式有兩種格式:
- CASE 簡(jiǎn)單表達(dá)式,它通過(guò)將表達(dá)式與一組簡(jiǎn)單的表達(dá)式進(jìn)行比較來(lái)確定結(jié)果宋距。
- CASE 搜索表達(dá)式轴踱,它通過(guò)計(jì)算一組布爾表達(dá)式來(lái)確定結(jié)果。
這兩種格式都支持可選的 ELSE 參數(shù)谚赎。
??CASE 可用于允許使用有效表達(dá)式的任意語(yǔ)句或子句淫僻。 例如,可以在 SELECT壶唤、UPDATE雳灵、DELETE 和 SET 等語(yǔ)句以及 select_list、IN闸盔、WHERE悯辙、ORDER BY 和 HAVING 等子句中使用 CASE。
??CASE語(yǔ)法:
--簡(jiǎn)單Case函數(shù)
CASE input_expression
WHEN when_expression THEN result_expression [ ...n ]
[ ELSE else_result_expression ]
END
--Case搜索函數(shù)
CASE
WHEN Boolean_expression THEN result_expression [ ...n ]
[ ELSE else_result_expression ]
END
【返回類型】從的類型集中返回優(yōu)先級(jí)高的類型result_expressions和可選else_result_expression迎吵。
CASE 表達(dá)式不能用于控制 Transact-SQL 語(yǔ)句笑撞、語(yǔ)句塊、用戶定義函數(shù)以及存儲(chǔ)過(guò)程的執(zhí)行流钓觉。能控制的只有IF..ELSE、WHILE這樣的控制流語(yǔ)言坚踩。
【示例】
A. 使用帶有 CASE 簡(jiǎn)單表達(dá)式的 SELECT 語(yǔ)句
SELECT ProductNumber, Category =
CASE ProductLine
WHEN 'R' THEN 'Road'
WHEN 'M' THEN 'Mountain'
WHEN 'T' THEN 'Touring'
WHEN 'S' THEN 'Other sale items'
ELSE 'Not for sale'
END,
Name
FROM Production.Product
ORDER BY ProductNumber;
GO
B. 使用帶有 CASE 搜索表達(dá)式的 SELECT 語(yǔ)句
在 SELECT 語(yǔ)句中荡灾,CASE 搜索表達(dá)式允許根據(jù)比較值替換結(jié)果集中的值。 下面的示例根據(jù)產(chǎn)品的價(jià)格范圍將標(biāo)價(jià)顯示為文本注釋瞬铸。
SELECT ProductNumber, Name, "Price Range" =
CASE
WHEN ListPrice = 0 THEN 'Mfg item - not for resale'
WHEN ListPrice < 50 THEN 'Under $50'
WHEN ListPrice >= 50 and ListPrice < 250 THEN 'Under $250'
WHEN ListPrice >= 250 and ListPrice < 1000 THEN 'Under $1000'
ELSE 'Over $1000'
END
FROM Production.Product
ORDER BY ProductNumber ;
GO
C. 在 ORDER BY 子句中使用 CASE
下面的示例在 ORDER BY 子句中使用 CASE 表達(dá)式批幌,以根據(jù)給定的列值確定行的排序順序。
SELECT BusinessEntityID, SalariedFlag
FROM HumanResources.Employee
ORDER BY CASE SalariedFlag WHEN 1 THEN BusinessEntityID END DESC
,CASE WHEN SalariedFlag = 0 THEN BusinessEntityID END;
GO
D. 在 SET 語(yǔ)句中使用 CASE
SET @ContactType =
CASE
-- Check for employee
WHEN EXISTS(SELECT * FROM HumanResources.Employee AS e
WHERE e.BusinessEntityID = @BusinessEntityID)
THEN 'Employee'
-- Check for vendor
WHEN EXISTS(SELECT * FROM Person.BusinessEntityContact AS bec
WHERE bec.BusinessEntityID = @BusinessEntityID)
THEN 'Vendor'
-- Check for store
WHEN EXISTS(SELECT * FROM Purchasing.Vendor AS v
WHERE v.BusinessEntityID = @BusinessEntityID)
THEN 'Store Contact'
-- Check for individual consumer
WHEN EXISTS(SELECT * FROM Sales.Customer AS c
WHERE c.PersonID = @BusinessEntityID)
THEN 'Consumer'
END;
循環(huán)語(yǔ)句
T-SQL中的循環(huán)語(yǔ)句只有while一種語(yǔ)法形式嗓节,while語(yǔ)句還可以和break荧缘、continue語(yǔ)句一起使用。其結(jié)構(gòu)如下所示:
WHILE Boolean_expression
{ sql_statement | statement_block | BREAK | CONTINUE }
- WHILE語(yǔ)句可以嵌套
- WHILE語(yǔ)句間不只包含一條語(yǔ)句時(shí)拦宣,必須使用BEGIN...END包含多條語(yǔ)句的語(yǔ)句塊截粗。
- CONTINUE:使 WHILE 循環(huán)重新開(kāi)始執(zhí)行,忽略 CONTINUE 關(guān)鍵字后面的任何語(yǔ)句鸵隧。
- BREAK:導(dǎo)致從最內(nèi)層的 WHILE 循環(huán)中退出绸罗。 執(zhí)行標(biāo)記的末尾循環(huán)中,在結(jié)束關(guān)鍵字后顯示的任何語(yǔ)句豆瘫。
- 如果嵌套了兩個(gè)或多個(gè) WHILE 循環(huán)珊蟀,則內(nèi)層的 BREAK 將退出到下一個(gè)外層循環(huán)。 將首先運(yùn)行內(nèi)層循環(huán)結(jié)束之后的所有語(yǔ)句外驱,然后重新開(kāi)始下一個(gè)外層循環(huán)育灸。
【示例】
USE AdventureWorks2012;
GO
WHILE (SELECT AVG(ListPrice) FROM Production.Product) < $300
BEGIN
UPDATE Production.Product SET ListPrice = ListPrice * 2
SELECT MAX(ListPrice) FROM Production.Product
IF (SELECT MAX(ListPrice) FROM Production.Product) > $500
BREAK
ELSE
CONTINUE
END
PRINT 'Too much for the market to bear';
其他控制語(yǔ)句
①WAITFOR語(yǔ)句
??waitfor語(yǔ)句稱為延時(shí)語(yǔ)句腻窒,它的功能暫停程序執(zhí)行,直到所設(shè)定的等待時(shí)間已過(guò)或所設(shè)定的時(shí)間已到才繼續(xù)玩下執(zhí)行磅崭。儿子。其語(yǔ)法如下:
WAITFOR
{
DELAY 'time_to_pass'
| TIME 'time_to_execute'
| [ ( receive_statement ) | ( get_conversation_group_statement ) ]
[ , TIMEOUT timeout ]
}
- DELAY:用來(lái)設(shè)定等待時(shí)間,最多可達(dá)24小時(shí)绽诚。
- time_to_pass:等待的時(shí)段典徊。 time_to_pass可接受格式之一指定datetime數(shù)據(jù),也可以指定為本地變量恩够。
- TIME:指定的運(yùn)行批處理卒落、存儲(chǔ)過(guò)程或事務(wù)的時(shí)間。
- time_to_execute:WAITFOR 語(yǔ)句完成的時(shí)間蜂桶。 time_to_execute可接受格式之一指定datetime數(shù)據(jù)儡毕,也可以指定為本地變量。
【示例】
A. 使用 WAITFOR TIME
下面的示例在晚上 10:20 在 msdb 數(shù)據(jù)庫(kù)中執(zhí)行 sp_update_job 存儲(chǔ)過(guò)程扑媚。
EXECUTE sp_add_job @job_name = 'TestJob';
BEGIN
WAITFOR TIME '22:20';
EXECUTE sp_update_job @job_name = 'TestJob',
@new_name = 'UpdatedJob';
END;
GO
B. 使用 WAITFOR DELAY
以下示例在兩小時(shí)的延遲后執(zhí)行存儲(chǔ)過(guò)程腰湾。
BEGIN
WAITFOR DELAY '02:00';
EXECUTE sp_helpdb;
END;
GO
C. 在 WAITFOR DELAY 中使用局部變量
以下示例顯示如何對(duì) WAITFOR DELAY 選項(xiàng)使用局部變量。 將創(chuàng)建一個(gè)存儲(chǔ)過(guò)程疆股,該過(guò)程將等待可變的時(shí)間段费坊,然后將經(jīng)過(guò)的小時(shí)、分鐘和秒數(shù)信息返回給用戶旬痹。
CREATE PROCEDURE dbo.TimeDelay_hh_mm_ss
(@DelayLength char(8)= '00:00:00')
AS
DECLARE @ReturnInfo varchar(255)
IF ISDATE('2000-01-01 ' + @DelayLength + '.000') = 0
BEGIN
SELECT @ReturnInfo = 'Invalid time ' + @DelayLength
+ ',hh:mm:ss, submitted.';
PRINT @ReturnInfo
RETURN(1)
END
BEGIN
WAITFOR DELAY @DelayLength
SELECT @ReturnInfo = 'A total time of ' + @DelayLength + ',
hh:mm:ss, has elapsed! Your time is up.'
PRINT @ReturnInfo;
END;
GO
EXEC TimeDelay_hh_mm_ss '00:00:10';
GO
②RETURN語(yǔ)句
??從查詢或過(guò)程中無(wú)條件退出附井。 RETURN 的執(zhí)行是即時(shí)且完全的,可在任何時(shí)候用于從過(guò)程两残、批處理或語(yǔ)句塊中退出永毅。 RETURN 之后的語(yǔ)句是不執(zhí)行的。其語(yǔ)法如下:
RETURN [<整形表達(dá)式>]
錯(cuò)誤處理語(yǔ)句
a. 簡(jiǎn)單的異常處理
??在T-SQL程序中人弓,把可能出現(xiàn)異常的程序語(yǔ)句放置在try部分(begin try...end tey)沼死,錯(cuò)誤處理語(yǔ)句放置在catch部分(begin catch...end catch),如果在try部分未發(fā)生錯(cuò)誤崔赌,則catch部分的語(yǔ)句會(huì)被忽略意蛀,如果try部分的語(yǔ)句發(fā)生了異常,則程序控制轉(zhuǎn)移至相應(yīng)的catch部分峰鄙。如果try..catch捕獲了錯(cuò)誤并進(jìn)行了處理浸间,對(duì)于調(diào)用者來(lái)說(shuō),相當(dāng)于沒(méi)發(fā)生錯(cuò)誤吟榴。
??如下面語(yǔ)句在try部分不會(huì)發(fā)生錯(cuò)誤魁蒜,catch部分的語(yǔ)句也不會(huì)被執(zhí)行:
begin try
print 10/2;
print 'No error';
end try
begin catch
print 'Error!Divided by zero.'
end catch
b. 預(yù)定義異常
??在一般T-SQL程序設(shè)計(jì)中,編程者應(yīng)該在catch部分分析錯(cuò)誤原因,然后給出相應(yīng)提示信息或其他處理語(yǔ)句兜看。
??catch部分捕獲到的錯(cuò)誤以錯(cuò)誤號(hào)來(lái)標(biāo)識(shí)锥咸,編程者通過(guò)調(diào)用error-numer()函數(shù)得到捕獲到的錯(cuò)誤號(hào),然后根據(jù)錯(cuò)誤號(hào)給出相關(guān)錯(cuò)誤提示信息细移,或者調(diào)用error-message()函數(shù)顯示系統(tǒng)預(yù)先定義的錯(cuò)誤信息搏予,SQL Server的所有預(yù)定以錯(cuò)誤號(hào)及對(duì)應(yīng)錯(cuò)誤信息可以通過(guò)查詢sys.message得到。另外弧轧,SQL Server不支持用戶自定義異常雪侥。
??下面示例說(shuō)明try...catch的用法。創(chuàng)建表t精绎,用于測(cè)試:
1> create table t
2> (
3> a int not null,
4> b int not null,
5> c char(4),
6> constraint pk_t primary key(a),
7> constraint ck_b check(b>100)
8> )
然后執(zhí)行下面程序段:
begin try
insert into t values(1,170,'a');
end try
begin catch
if error_number() = 2627
begin
print 'Handling PK violation...';
end
else if error_number() = 547
begin
print 'Handling CHECK/FK constraint violation...';
end
else if error_number() = 515
begin
print 'Handling NULL violation...';
end
else if error_number() = 245
begin
print 'Handling conversion error...';
end
else
begin
print 'Handling unknow error...';
end
-- 輸出錯(cuò)誤號(hào)
print 'Error Number:'+cast(error_number() as varchar(10));
-- 輸出錯(cuò)誤信息
print 'Error Message:'+error_message();
print 'Error Severity:'+cast(error_severity() as varchar(10));
print 'Error State:'+cast(error_state() as varchar(10));
print 'Error Line:'+cast(error_line() as varchar(10));
print 'Error Proc:'+coalesce(error_procedure(),'Not within proc');
end catch
如果第二次執(zhí)行上面的語(yǔ)句速缨,則會(huì)因?yàn)橹麈I存在重復(fù)值而給出以下錯(cuò)誤信息:
Handling PK violation...
Error Number:2627
Error Message:違反了 PRIMARY KEY 約束 'pk_t'。不能在對(duì)象 'dbo.t' 中插入重復(fù)鍵代乃。
Error Severity:14
Error State:1
Error Line:2
Error Proc:Not within proc
如果把添加記錄的insert語(yǔ)句改為:
??insert into t values(2,10,'a');
??修改后旬牲,重新執(zhí)行上述程序段,則違反了b字段上的check約束搁吓,會(huì)給出以下錯(cuò)誤信息:
Handling CHECK/FK constraint violation...
Error Number:547
Error Message:INSERT 語(yǔ)句與 CHECK 約束"ck_b"沖突原茅。該沖突發(fā)生于數(shù)據(jù)庫(kù)"master", 表"dbo.t", column 'b'堕仔。
Error Severity:16
Error State:0
Error Line:2
Error Proc:Not within proc
c. 使用存儲(chǔ)過(guò)程處理異常
??如果要使得錯(cuò)誤處理的代碼可以重用擂橘,則可以把上述catch的內(nèi)容創(chuàng)建為存儲(chǔ)過(guò)程,以后即可在T-SQL代碼中直接調(diào)用摩骨。
??創(chuàng)建存儲(chǔ)過(guò)程如下:
create procedure dbo.err_message
as
if error_number() = 2627
begin
print 'Handling PK violation...';
end
else if error_number() = 547
begin
print 'Handling CHECK/FK constraint violation...';
end
else if error_number() = 515
begin
print 'Handling NULL violation...';
end
else if error_number() = 245
begin
print 'Handling conversion error...';
end
else
begin
print 'Handling unknow error...';
end
-- 輸出錯(cuò)誤號(hào)
print 'Error Number:'+cast(error_number() as varchar(10));
-- 輸出錯(cuò)誤信息
print 'Error Message:'+error_message();
print 'Error Severity:'+cast(error_severity() as varchar(10));
print 'Error State:'+cast(error_state() as varchar(10));
print 'Error Line:'+cast(error_line() as varchar(10));
print 'Error Proc:'+coalesce(error_procedure(),'Not within proc');
在T-SQL程序段中調(diào)用上述存儲(chǔ)過(guò)程:
begin try
insert into t values(2,10,'a');
end try
begin catch
exec err_message;
end catch