王朝网络
分享
 
 
 

《MS SQL Server 2000管理员手册》系列——20. 认识进阶的 T-SQL

王朝mssql·作者佚名  2006-02-01
宽屏版  字体: |||超大  

20. 认识进阶的 T-SQL

INSERT 陈述式

UPDATE 陈述式

DELETE 陈述式

程序设计关键词

本章总结

本章将详细讨论前面章节所使用过用来修改数据的T-SQL陈述式,加上一些可用来控制程序设计流程的T-SQL关键词。这些陈述式及关键词可用于任何可以使用T-SQL的地方,如使用在指令行、指令码、预存程序、批次文件和应用程序中。我们会特别学习有关数据处理的陈述式,如INSERT、UPDATE和DELETE(这些陈述式在 第十三章 曾经提到过),以及程序结构,如IF、WHILE和CASE。

首先我们为范例建立一个数据表,命名为items(请将该数据表建立在MyDB数据库内),以下为建立items数据表的T-SQL命令:

USE MyDB

GO

CREATE TABLE items

(

item_category CHAR(20) NOT NULL,

item_id SMALLINT NOT NULL,

price SMALLMONEY NULL,

item_desc VARCHAR(30) DEFAULT 'No desc'

)

GO

item_id数据行适合设成IDENTITY属性(请参阅 第十章的〈增加IDENTITY属性〉 。但由于识别数据行不允许直接插入值,因此这里不使用IDENTITY;这样才可以更有弹性的使用包含INSERT陈述式的范例。

INSERT陈述式

在 十三章 曾介绍过INSERT陈述式,可以用来新增数据列至数据表或检视表。以下为INSERT陈述式的基本语法:

INSERT [INTO] table_name [(column_list)] VALUES

expression | derived_table

INTO关键词和 数据行清单(column_list) 参数可依需要而设定。 数据行清单 参数指定了要插入值的数据行,这些值和表达式中所列的值按顺序对应(也可以只包含值的清单)。

插入资料列

下面范例示范如何插入数据列至items数据表。

INSERT INTO items

(item_category, item_id, price, item_desc)

VALUES ('health food', 1, 4.00, 'tofu 6 oz.')

GO

由于已经替数据表中的每个数据行都指定了一个值,而且依照数据列在数据表中定义的顺序列出对应的值,因此我们也可以不必使用 数据行清单 。但是如果值不是依数据行的顺序排列,输入的数据就可能不正确,或是收到错误讯息。举例来说,试着执行以下的陈述式,就会收到错误讯息:

INSERT INTO items

VALUES (1, 'health food', 4.00, 'tofu 6 oz.')

GO

服务器:讯息245,层级16,状态1,行1

将varchar数值 'health food' 转换成数据型别为smallint的数据行语法错

误。

由于值所放置的顺序不正确,因此数据列并没有被插入,并传回错误讯息。我们尝试把item_id插入item_category数据行,item_category插入item_id数据行(两个数据输入的顺序颠倒),两个不同数据型别的数据并不兼容,当然,如果两个数据行的型别是兼容的,就算数值不同,数据也会被插入,不过数据虽然被插入,却是不正确的数据。

要看看插入的列在数据表中如何显示,使用下面的SELECT陈述式查询资料表,以选择所有的列。

SELECT * from items

GO

会看到以下的结果集:

item_category item_id price item_desc

-------------- ------------- ----------

health food 1 4.00 tofu 6 oz.

当建立items数据表时,price数据行定义为允许NULL值,item_desc(描述)数据行的默认值为No desc。如果INSERT陈述式中没有替price数据行指定一个值,新数据列中将插入NULL;如果item_desc数据行没有指定一个值,将插入默认值No desc。

省略资料行值

在前面INSERT陈述式范例中,由于price数据行和item_desc数据行设有默认值,所以可以省略数据行的值和名称。如果要省略数据行的值,必须为其它在 数据行清单 的数据行指定参数,否则,列出的值将依照数据表中数据行定义的顺序,分配给各数据行。

举例来说,我们照下面这样输入:在 数据行清单 中少输入了一行价钱,也没有为 数据行清单 指定值。

INSERT INTO items

VALUES ('junk food', 2, 'fried pork skins')

GO

SQL Server会试着把item_desc(值清单中的第三个值)提供的值(fried pork skins)插入price数据行(数据表中的第三字段)。由于price数据行为smallmoney数据型别,fried pork skins是char数据型别,两个不兼容的数据型别,就会产生如下的错误讯息:

服务器:讯息213,层级16,状态4,行1

插入错误:数据行名称或提供的数值数量与数据表定义不相符。

试想如果fried pork skins的数据型别和price数据行兼容,数据就会被不正确的插入,也影响了整个数据表的一致性与正确性。

记住插入数据表或检视表的值的数据型别必须和字段定义的数据型别兼容。还有,如果插入的数据列违反了规则或条件约束,会产生错误讯息,数据列也不会被插入。

为了避免不兼容数据型别的错误发生,指定 数据行清单 以符合应当被插入的值,如下所示:

INSERT INTO items

(item_category, item_id, item_desc)

VALUES ('junk food', 2, 'fried pork skins')

GO

由于没有指定价格,price数据行将插入NULL值。执行下面的SELECT陈述式:

SELECT * FROM items

应该会出现下述的结果集,结果集中包含已插入的两个数据列,注意price数据列中的NULL。

item_category item_id price item_desc

-------------- -------------- -----------------

health food 1 4.00 tofu 6 oz.

junk food 2 NULL fried pork skins

现在增加另一数据列,不要指定price数据行或item_desc数据行的值,如下所示:

INSERT INTO items

(item_category, item_id)

VALUES ('toy', 3)

GO

使用下面的查询就可以得到该列的结果集:

SELECT * FROM items WHERE item_id = 3

结果集如下所示:

item_category item_id price item_desc

-------------- -------------- ------------

toys 3 NULL No desc

注意price数据行中的NULL和item_desc资料列中的No desc。这些值可用稍后本章将介绍的UPDATE陈述式变更。

有四种类型的数据行,在没有指定值时,SQL Server会自动提供值给该数据行:分别是 允许NULL值 、 设定默认值 、 IDENTITY属性 和 时间戳记(timestamp) 的数据行。之前讨论过允许NULL值的数据行和含默认值的数据行,若没有指定值会产生的情形(在 第十章 讨论过)。大部分的情况下,是不能手动插入数据值到这两种类型的数据行中。

________________________________________

说明

在数据表中执行INSERT操作时要谨慎。请确定插入的数据正确地放入应当插入的数据行。确定测试了所有的T-SQL程序代码后,再存取或修改数据。

________________________________________

从另一数据表中新增数据列

您可以从数据表插入数据列到另一个资料表中。这可以透过在INSERT陈述式中使用衍生资料表,或在传回数据列的预存程序中使用EXECUTE子句来完成。

________________________________________

说明

衍生数据表(Derived Table)即为来自另一个T-SQL陈述式FROM子句中的SELECT陈述式结果集,在 第十四章 中会讨论到衍生数据表。

________________________________________

现在来示范如何使用衍生数据表插入数据。首先建立数据表,命名为two_newest_items,并将item资料表中的两笔数据列插入two_newest_items,以下是建立新数据表所使用的CREATE TABLE陈述式:

CREATE TABLE two_newest_items

(

item_id SMALLINT NOT NULL,

item_desc VARCHAR(30) DEFAULT 'no desc'

)

GO

要从items数据表将item_id和item_desc资料行中最新的值插入two_newest_items数据表,请使用下面的INSERT陈述式:

INSERT INTO two_newest_items

(item_id, item_desc)

SELECT TOP 2 item_id, item_desc FROM items

ORDER BY item_id DESC

GO

请注意这里使用的是SELECT陈述式,而不是列在INSERT陈述式的值清单。SELECT陈述式从一个已存在的数据表中传回数据,传回的数据当成值清单。另外,注意在SELECT陈述式上并没有加括号,因为括号将造成传回语法错误。

要查询新数据表中所有数据列,可使用下列程序代码:

SELECT * FROM two_newest_items

所显示的结果集如下:

item_id item_desc

-------------------------

3 No desc

2 fried pork skins

请注意,我们在这里的INSERT陈述式中使用ORDER BY子句,使item_id的数据列递减排序。

如果我们将前面的SELECT陈述式建立为预存程序,使用EXECUTE陈述式加上预存程序名称,也可以得到同样的结果(预存程序将会在 第二十一章 介绍)。操作的方法为,首先使用DELETE陈述式删除two_newest_items数据表中现存的所有数据列。(详细细节请参阅本章稍后的 〈DELETE陈述式〉 。)然后建立一个预存程序,命名top_two,并用EXECUTE陈述式插入两个新数据列到two_newest_items数据表。操作的T-SQL陈述式为:

DELETE FROM two_newest_items

GO

CREATE PROCEDURE top_two

AS

SELECT TOP 2 item_id, item_desc FROM items

ORDER BY item_id DESC

GO

INSERT INTO two_newest_items

(item_id, item_desc)

EXECUTE top_two

GO

现在可以看到,我们已经使用top_two预存程序成功地插入两个新的数据列。

________________________________________

相关信息

INSERT陈述式可以用于指定数据表提示(Table Hints)。要详细了解可以和INSERT陈述式一起使用的数据表提示,请使用《在线丛书》,在搜寻标签页中输入 锁定提示 ,选择 锁定提示 主题。

________________________________________

UPDATE陈述式

UPDATE陈述式用于修改或更新存在的数据,基本语法如下:

UPDATEtable_nameSETcolumn_name = expression

[FROMtable_source] WHERE search_condition

更新数据列

本范例将使用之前的items范例数据表,首先更新之前没有输入价格的junk food数据列。要识别数据列,将搜寻条件指定为fried pork skins,用下列陈述式更新价格至 $2元:

UPDATE items SET price = 2.00

WHERE item_desc = 'fried pork skins'

GO

然后使用查询选出junk food数据列:

SELECT * FROM items

WHERE item_desc = 'fried pork skins'

GO

junk food数据列输出显示如下,原来的NULL值被2.00所替代:

item_category item_id price item_desc

-------------- ----------------------- ------------

junk food 2 2.00 fried pork skins

您也可以使用以下的陈述式将价格增加10%:

UPDATE items SET price = price * 1.10

WHERE item_desc = 'fried pork skins'

GO

现在如果选择junk food数据列,价格已变更至 $2.20($2乘以1.10的结果);其它项目的价格则维持不变。

使用UPDATE陈述式可以更新一个以上的资料列。举例来说,可以将所有数据列的价格都增加10%,其陈述式如下:

UPDATE items SET price = price * 1.10

GO

得到的输出结果如下:

item_category item_id price item_desc

--------------- --------------- -----------------

health food 1 4.40 tofu 6 oz.

junk food 2 2.42 fried pork skins

toys 3 NULL No desc

价格设为NULL的数据列不会变动(因为NULL* 1.10还是等于NULL),这样的执行方式是可以接受的,不会产生错误讯息。

使用FROM子句

UPDATE陈述式可利用FROM子句指定更新操作中的数据来源,数据来源清单可以包含数据表名称、检视表名称、数据列及函数、衍生数据表和联结数据表,甚至更新中的数据表也可以当成数据表来源。以下是范例,首先利用CREATE TABLE陈述式建立一个新的数据表,命名为tax,再用INSERT陈述式插入新的数据列,在tax_percent数据行中将值设为5.25。

CREATE TABLE tax

(

tax_percent real NOT NULL,

change_date smalldatetime DEFAULT getdate( )

)

GO

INSERT INTO tax

(tax_percent) VALUES (5.25)

GO

由于没有设定日期和时间,change_date数据行会使用默认值,由GETDATE函数得到目前的日期和时间。

现在在item数据表中新增一个新的数据行,命名为price_with_tax,并允许NULL值,陈述式如下:

ALTER TABLE items

ADD price_with_tax smallmoney NULL

GO

接下来要更新所有price_with_tax数据行,这个数据行的数据是由items.price * tax.tax_percent运算而来。使用UPDATE陈述式和FROM子句如下:

UPDATE items

SET price_with_tax = i.price +

(i.price * t.tax_percent / 100)

FROM items i, tax t

GO

在price数据行有数值的数据列,在price_with_tax数据行也会出现运算后的数值;如果原price数据行的数据为NULL,则相对应的price_with_tax也会出现NULL(NULL乘以任何值还是NULL),运算后的结果集如下(结果也包含所有先前对数据所做的修改):

item_category item_id price item_desc price_with_tax

-------------- ------- ------ --------------- ------------------

health food 1 4.40 tofu 6 oz 4.63

junk food 2 2.42 fried pork skin 2.55

toys 3 NULL No desc NULL

如果在数据表中新增记录,可以考虑执行之前的UPDATE陈述式,但这样会再次更新price_with_tax数据行,浪费程序时间。要避免这种情况,可以使用UPDATE陈述式的WHERE子句,让SQL Server更新price_with_tax中只含有NULL值的数据行。

UPDATE items

SET price_with_tax = i.price +

(i.price * t.tax_percent / 100)

FROM items i, tax t

WHERE i.price_with_tax IS NULL

GO

UPDATE陈述式非常适合当作触发程序,当插入一个值到price数据行时,便会执行。触发程序是一种特殊的预存程序,在某一特定的条件下会自动执行。触发程序将在 第二十二章 中加以讨论。

使用衍生数据表

使用UPDATE陈述式的另一个方法是在FROM子句中附带一个衍生数据表或子查询。然后衍生数据表就可以当成外部UPDATE的输入。使用范例,我们将在子查询中使用two_newest_items数据表,在外部UPDATE陈述式中使用items数据表。我们想要更新items数据表中的两列数据,以使price_with_tax数据行储存NULL值,可以利用查询two_newest_items数据表,即可找出数据列中需要更新的item_id值:

UPDATE items

SET price_with_tax = NULL

FROM (SELECT item_id FROM two_newest_items) AS t1

WHERE items.item_id = t1.item_id

GO

SELECT陈述式当成子查询,其结果会放入命名为t1的暂存衍生数据表中,此数据表会被WHERE子句当成搜寻条件。子查询的结果产生item_id的2和3两个值,只要在item_id数据行中有2或3这两个值,就会被影响。在item_id值为3的资料列,因为对应的price_with_tax数据行已有NULL值,故不会再改变;而在item_id值为2的数据列则更新为NULL值。结果集如下:

item_category item_id price item_desc price_with_tax

-------------- ------- ----- --------------- --------------

health food 1 4.40 tofu 6 oz. 2.30

junk food 2 2.42 fried pork skins NULL

toys 3 NULL No desc NULL

DELETE陈述式

DELETE陈述式用于从数据表或检视表中移除(删除)一个或多个数据列。DELETE不影响数据表定义;只是从数据表中删除数据列。DELETE陈述式的基本语法如下:

DELETE [FROM]table_name|view_name

[FROMtable_sources] WHEREsearch_condition

第一个和第二个FROM关键词可视需要使用。在第二个FROM子句中,数据表来源中的数据列不会被删除,但会从DELETE后指定的table_name或view_name中被删除。

删除个别数据列

在DELETE中使用WHERE子句,可以指定从资料表中删除特定的数据列。举例来说,要从items数据表中删除item_category中toy这个数据列,执行下面的叙述:

DELETE FROM items

WHERE item_category = 'toy'

GO

该陈述式从items资料表中删掉了一列。

使用一个或多个数据表来源的第二个FROM子句,可指定其它数据表或检视表,供WHERE搜寻条件使用。例如,要从items数据表中删除对应于two_newest_items数据表中的数据列,可执行下面的陈述式:

DELETE items

FROM two_newest_items

WHERE items.item_id = two_newest_items.item_id

GO

请注意,在这个陈述式中,two_newest_items数据表中的item_id数据列含有2和3的值,而items数据表中的item_id数据列则含有1和2的值,所以2就被删除(因为符合搜寻条件)。在two_newest_items数据表(数据来源)的两个数据列则不受影响。

删除所有数据列

要删除数据表中的所有数据列,可利用DELETE陈述式。下面的DELETE陈述式将删除two_newest_items数据表中的所有数据列:

DELETE FROM two_newest_items

GO

现在two_newest_items数据表是一个空的数据表,即不包含数据列的数据表。如果想删除数据表定义,请使用 第十五章 说明的DROP TABLE指令:

DROP TABLE two_newest_items

GO

________________________________________

相关信息

在《在线丛书》中可找到更多使用DELETE的方法,例如利用联结数据表作为数据表来源,以及使用数据表和查询提示,请在《在线丛书》索引中查阅DELETE并选择相关的次主题。

________________________________________

程序设计关键词

T-SQL陈述式中有几个有用的程序设计结构关键词,能用来控制程序流程。这些结构可用于批处理(一次执行一组T-SQL陈述式)、预存程序、指令码和特别的查询(本节范例会使用pubs数据库)。

IF...ELSE

IF...ELSE结构利用条件以决定将执行那一条T-SQL陈述式,语法如下:

IFBoolean_expression

T-SQL_statement | block_of_statements

[ELSET-SQL_statement | block_of_statements]

布尔表达式(Boolean Expression)指的是传回TRUE或FALSE的表达式。如果IF子句中的表达式传回TRUE,陈述式将执行,ELSE子句及其叙述则不执行;如果表达式传回FALSE,就会只执行ELSE关键词后的叙述。 陈述式区块(block_of_statements) 代表一个以上的T-SQL陈述式。使用陈述式区块时,无论该陈述式区块在IF子句中、ELSE子句中或是两者都有,都必须用关键词BEGIN和END来指定区块的开始和结束。

您也可以使用没有ELSE子句的IF子句。现在我们先来看看只使用IF子句的范例,下面的程序代码将检查表达式,如果表达式传回TRUE,将执行接下来的PRINT陈述式:

IF (SELECT ytd_sales FROM titles

WHERE title_id = 'PC1035') > 5000

PRINT 'year-to-date sales are

greater than $5,000 for PC1035.'

GO

因为title_id = 'PC1035'数据列ytd_sales的值是8780(大于5000),因此IF表达式将计算为TRUE,并执行PRINT陈述式,将「Year-to-date sales are greater than $5,000 for PC1035」打印在屏幕上。

现在将一个ELSE子句新增到上面的范例中,并将> 5000变为> 9000。IF...ELSE显示如下:

IF (SELECT ytd_sales FROM titles

WHERE title_id = 'PC1035') > 9000

PRINT 'yeartodate sales are

greater than $9,000 for PC1035.'

ELSE

PRINT 'yeartodate sales are

less than $9,000 for PC1035.'

GO

在本范例中,由于IF表达式传回FALSE。ELSE子句后的打印陈述式将被执行。

让我们更进一步扩展以上的范例,并在IF和ELSE子句中新增陈述式区块。根据IF条件传回的结果,打印讯息后执行查询,下面是范例程序代码:

IF (SELECT ytd_sales FROM titles WHERE title_id = 'PC1035') > 9000

BEGIN

PRINT 'year-to-date sales are

greater than $9,000 for PC1035.'

SELECT ytd_sales FROM titles

WHERE title_id = 'PC1035'

END

ELSE -- ytd_sales必须小与或等于9000.

BEGIN

PRINT 'year-to-date sales are

less than or equal to $9,000 for PC1035.'

SELECT price FROM titles

WHERE title_id = 'PC1035'

END

GO

IF计算式结果是FALSE,所以会执行ELSE子句中BEGIN和END之间的叙述:执行PRINT后接着执行SELECT陈述式,显示书价为 $22.95。

您也可以在IF子句或ELSE子句后使用巢状的IF陈述式。举例来说,可执行下面的程序代码,使用巢状的IF...ELSE陈述式找出ytd_sales平均值的范围:

IF (SELECT avg(ytd_sales) FROM titles) < 10000

IF (SELECT avg(ytd_sales) FROM titles) < 5000

IF (SELECT avg(ytd_sales) FROM titles) < 2000

PRINT 'Average year-to-date sales are

less than $2,000.'

ELSE

PRINT 'Average year-to-date_ sales are

between $2,000 and $4,999.'

ELSE

PRINT 'Average year-to-date sales are

between $5,000 and $9,999.'

ELSE

PRINT 'Average year-to-date sales are greater

than $9,999.'

GO

当您执行该程序代码时,将会看到两次这样的讯息:「警告:汇总(aggregate)或其它SET操作已消除Null值。」该讯息表示数据表计算平均数时,在ytd_sales数据行的NULL值未被使用,也未被当成值来计算。由于平均值是 $6,090,该程序代码所得到最后结果是「Average year-to-date sales are between $5,000 and $9,999.」。请注意,当使用IF陈述式时,很容易就把IF应该和哪个ELSE为一组混淆,或者有了IF但忘了指示ELSE,所以用TAB键(如上所示)是不错的办法。

WHILE

该条件判断式是设定SQL陈述式或陈述式区块重复执行的条件。只要指定条件为TRUE,陈述式会一直重复执行。这就是所谓的WHILE循环(Loop),因为WHILE结构中的程序代码在循环中重复。语法显示如下:

WHILEBoolean_expression

SQL_statement | block_of_statements

[BREAK]SQL_statement | block_of_statements

[CONTINUE]

同上述的IF...ELSE,使用BEGIN和END来指定WHILE循环中陈述式的起始和结束。BREAK关键词则将导致从WHILE循环中跳出,然后接着执行WHILE循环结束后的陈述式。如果一个WHILE循环与另一个WHILE循环是巢状结构,BREAK关键词只会从被包含的WHILE循环中跳出,继续执行该循环外所有的的陈述式和循环。CONTINUE关键词指定WHILE循环重新执行BEGIN和END之间的陈述式,忽略CONTINUE之后的其它陈述式。

现在使用简单的WHILE循环重复执行UPDATE陈述式。WHILE循环的检测条件为:royalty资料行的平均值是否少于20。如果检测传回TRUE,所有royalty数据列的值都会增加5%。接着再次检测WHILE条件,重复更新直到royalty字段的平均值为20或更多。程序代码如下:

WHILE (SELECT AVG(royalty) FROM roysched) < 20

UPDATE roysched SET royalty = royalty * 1.05

GO

由于royalty数据行原来的平均值是15,因此在平均值达到20前,WHILE循环共执行了21次,直到检测条件回传值为FALSE时才停止。

现在看一个在WHILE循环中使用BREAK、CONTINUE、BEGIN和END的范例。我们将执行循环直到royalty的平均值达到25。但如果在循环中,royalty的最大值超过27,将中断循环,并在WHILE循环结束后加一个SELECT陈述式。下面是T-SQL程序代码:

WHILE (SELECT AVG(royalty) FROM roysched) < 25

BEGIN

UPDATE roysched SET royalty = royalty * 1.05

IF (SELECT MAX(royalty) FROM roysched) > 27

BREAK

ELSE

CONTINUE

END

SELECT MAX(royalty) AS "MAX royalty" FROM roysched

GO

数据表中已经存在的royalty值大于27,因此只执行一次循环,而royalty的平均值小于25%,因此UPDATE执行一次;接着IF陈述式检测并传回TRUE,所以执行BREAK,跳出WHILE循环;最后执行END关键词后的陈述式,也就是SELECT陈述式。

您还能使用巢状的WHILE循环,但记得BREAK或CONTINUE关键词只应用于呼叫它们的循环,而不是外部的WHILE循环。

CASE

CASE关键词用来评估各种条件的清单,并且传回多种可能的结果表达式其中之一,最常见的用法是用来取代程序代码,或是使用具可读性的数值(缩写值),或者用来分类值,本节的范例将加以介绍。CASE被分为两种格式:简单(simple)格式和搜寻(searched)格式。简单格式会使用CASE之后的表达式,与一组在WHEN之后的表达式做比较,以决定其结果;搜寻格式则评估一组布尔表达式为TRUE或FALSE,以决定其结果。以下为简单格式的语法:

CASE input_expression

WHEN when_expression THEN result_expression

[WHEN when_expression THEN result_expression...n]

[ELSE else_result_expression]

END

when_expression和input_expression会依其在CASE子句中的排列顺序进行比较,如果相对应的when_expression等于input_expression,将传回result_expression值。如果没有对应的值,将传回指定的else_result_expression的值。如果没有指定else_result_expression,则传回NULL。注意在简单格式CASE子句中,input_expression值和when_expression值的数据型别必须相同,或是数据型别之间允许隐含转换。

下面的范例在SELECT陈述式中使用简单格式的CASE子句。Sales数据表的payterms数据行包含了Net 30、Net 60、On invoice或None。这个T-SQL陈述式允许使用替代值(易于了解)以显示payterms数据行:

SELECT 'Payment Terms' =

CASE payterms

WHEN 'Net 30' THEN 'Payable 30 days

after invoice'

WHEN 'Net 60' THEN 'Payable 60 days

after invoice'

WHEN 'On invoice' THEN 'Payable upon

receipt of invoice'

ELSE 'None'

END,

title_id

FROM sales

ORDER BY payterms

GO

CASE子句会检测payterms数据行中,被SELECT陈述式中所指定每个数据列的值。当when_expression值等于payterms值,传回result_expression的值。来自CASE子句的结果显示在结果集中的Payment Terms资料行中,如下所示:

Payment Terms title_id

------------------------------- -----------

Payable 30 days after invoice PC8888

Payable 30 days after invoice TC3218

Payable 30 days after invoice TC4203

Payable 30 days after invoice TC7777

Payable 30 days after invoice PS2091

Payable 30 days after invoice MC3021

Payable 30 days after invoice BU1111

Payable 30 days after invoice PC1035

Payable 60 days after invoice BU1032

Payable 60 days after invoice PS2091

Payable 60 days after invoice PS2091

Payable 60 days after invoice PS1372

Payable 60 days after invoice PS2106

Payable 60 days after invoice PS3333

Payable 60 days after invoice PS7777

Payable 60 days after invoice BU7832

Payable 60 days after invoice MC2222

Payable upon receipt of invoice PS2091

Payable upon receipt of invoice BU2075

Payable upon receipt of invoice MC3021

Payable upon receipt of invoice BU1032

(影响21个数据列)

现在我们来看看搜寻格式的CASE子句,语法如下:

CASE

WHENBoolean_expressionTHENresult_expression

[WHENBoolean_expressionTHENresult_expression...n]

[ELSEelse_result_expression]

END

简单格式与搜寻格式的CASE子句其区别在于:搜寻格式的CASE子句在CASE关键词后没有input_expression值,而在WHEN关键词后以Boolean表达式检测TRUE或FALSE,并不像简单格式比较表达式之间是否相等。搜寻格式的CASE子句依照各个表达式排列的顺序检测Boolean_expression值,并传回评估为TRUE的第一个result_expression值。

举例来说,下面的SELECT陈述式中的CASE子句将检测每一个数据列的price值,并且以书的价格范围为标准,比较数据列中的price值,传回一个字符串:

SELECT 'Price Range' =

CASE

WHEN price BETWEEN .01 AND 10.00

THEN 'Inexpensive: $10.00 or less'

WHEN price BETWEEN 10.01 AND 20.00

THEN 'Moderate: $10.01 to $20.00'

WHEN price BETWEEN 20.01 AND 30.00

THEN 'Semi-expensive: $20.01 to $30.00'

WHEN price BETWEEN 30.01 AND 50.00

THEN 'Expensive: $30.01 to $50.00'

WHEN price IS NULL

THEN 'No price listed'

ELSE 'Very expensive!'

END,

title_id

FROM titles

ORDER BY price

GO

结果集显示如下:

Price Range title_id

------------------------------- ----------

No price listed MC3026

No price listed PC9999

Inexpensive: $10 or less MC3021

Inexpensive: $10 or less BU2075

Inexpensive: $10 or less PS2106

Inexpensive: $10 or less PS7777

Moderate: $10.01 to $20 PS2091

Moderate: $10.01 to $20 BU1111

Moderate: $10.01 to $20 TC4203

Moderate: $10.01 to $20 TC7777

Moderate: $10.01 to $20 BU1032

Moderate: $10.01 to $20 BU7832

Moderate: $10.01 to $20 MC2222

Moderate: $10.01 to $20 PS3333

Moderate: $10.01 to $20 PC8888

Semiexpensive: $20.01 to $30 TC3218

Semiexpensive: $20.01 to $30 PS1372

Semiexpensive: $20.01 to $30 PC1035

(影响18个数据列)

________________________________________

说明

以上两个CASE子句范例中,由于整个CASE子句是SELECT子句中 数据行清单 的一部份,所以我们在END关键词后插入了逗号后,才加入title_id数据行。换句话说,整个CASE子句在数据行清单中只是一个项目。这是CASE关键词最常被使用的方法。

________________________________________

其它关键词

以下为其它可用于控制程序流程的T-SQL关键词:

• GOTO label:当GOTO中定义了某label时,导向处理程序直接由该label后开始继续处理。

• RETURN :无条件从查询或程序中退出。

• WAITFOR :为陈述式的执行设定延迟或指定时间。

________________________________________

相关信息

要详细了解如何使用这些关键词,可在《在线丛书》索引中查阅GOTO、RETURN和WAITFOR,检视对话框中所列的主题。

________________________________________

本章总结

在本章中,您学到了使用INSERT、UPDATE和DELETE的T-SQL陈述式,以及用来控制程序流程的关键词IF、ELSE、WHILE、BEGIN、END和CASE。 第二十一章 将学习如何建立预存程序,配合使用这些陈述式和结构。

 
 
 
免责声明:本文为网络用户发布,其观点仅代表作者个人观点,与本站无关,本站仅提供信息存储服务。文中陈述内容未经本站证实,其真实性、完整性、及时性本站不作任何保证或承诺,请读者仅作参考,并请自行核实相关内容。
2023年上半年GDP全球前十五强
 百态   2023-10-24
美众议院议长启动对拜登的弹劾调查
 百态   2023-09-13
上海、济南、武汉等多地出现不明坠落物
 探索   2023-09-06
印度或要将国名改为“巴拉特”
 百态   2023-09-06
男子为女友送行,买票不登机被捕
 百态   2023-08-20
手机地震预警功能怎么开?
 干货   2023-08-06
女子4年卖2套房花700多万做美容:不但没变美脸,面部还出现变形
 百态   2023-08-04
住户一楼被水淹 还冲来8头猪
 百态   2023-07-31
女子体内爬出大量瓜子状活虫
 百态   2023-07-25
地球连续35年收到神秘规律性信号,网友:不要回答!
 探索   2023-07-21
全球镓价格本周大涨27%
 探索   2023-07-09
钱都流向了那些不缺钱的人,苦都留给了能吃苦的人
 探索   2023-07-02
倩女手游刀客魅者强控制(强混乱强眩晕强睡眠)和对应控制抗性的关系
 百态   2020-08-20
美国5月9日最新疫情:美国确诊人数突破131万
 百态   2020-05-09
荷兰政府宣布将集体辞职
 干货   2020-04-30
倩女幽魂手游师徒任务情义春秋猜成语答案逍遥观:鹏程万里
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案神机营:射石饮羽
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案昆仑山:拔刀相助
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案天工阁:鬼斧神工
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案丝路古道:单枪匹马
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:与虎谋皮
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:李代桃僵
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:指鹿为马
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案金陵:小鸟依人
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案金陵:千金买邻
 干货   2019-11-12
 
>>返回首页<<
推荐阅读
 
 
频道精选
 
静静地坐在废墟上,四周的荒凉一望无际,忽然觉得,凄凉也很美
© 2005- 王朝网络 版权所有