- 由浅入深学SQL Server:基础、进阶与必做300题
- 王俊 郑笛编著
- 237字
- 2024-12-21 18:24:56
第4章 掌握数据库查询语言T-SQL
创建用户数据库之后,接下来的重要工作就是创建、管理数据表及完成各种查询工作,而所有查询的基础都是SQL语言代码。SQL语言是一种介于关系代数与关系演算之间的语言,是一个通用的、功能极强的关系数据库语言。SQL语言的功能包括查询、操纵、定义和控制4个方面。本章将对SQL语言的基本构成、数据类型、控制流程进行详细讲解。
在本章中,将重点学习以下内容:
● T-SQL使用的数据类型。
● SQL Server 2008新增的数据类型。
● T-SQL中常量和变量的使用。
● T-SQL中注释符和运算符的使用。
● T-SQL中的流程控制命令。
4.1 T -SQL概述
SQL语言是1974年由Boyce和Chamberlin提出的,1975年至1979年IBM公司的San Jose Research Laboratory研制的关系数据库管理系统原型系统System R实现了这种语言。由于它功能丰富、语言简洁、使用方法灵活,备受用户和计算机业界的青睐,被众多的计算机公司和软件公司采用。经过多年的发展,SQL语言已成为关系数据库的标准语言。
1992年ISO(国际标准化组织)和IEC(国际电子技术委员会)共同发布了名为SQL92的SQL国际标准。ANSI(美国国家标准局)在美国发布了相应的ANSL SQL-92标准,该标准也称ANSI SQL。尽管不同的关系数据库使用各种不同的SQL版本,但多数都按ANSI SQL标准执行。
SQL Server 2008使用ANSI SQL-92的扩展集,即通常所说的Transact-SQL,简写为T-SQL。它是对标准SQL程序语言的增强,是用于应用程序和SQL Server 2008之间通信的主要语言。T-SQL在标准SQL语言的基础上扩充了许多功能,包括DDL(数据定义语言)、DML(数据操纵语言)、存储过程、系统表、函数、数据类型和流程控制语句。Transact-SQL语言的分类如下。
● 变量说明:用来说明变量的命令。
● 数据定义语言(DDL,Data Defin ition Lan guage):用来建立数据库、数据库对象和定义其列,大部分是以CREATE开头的命令,如CREATE TABLE、CREATE VIEW、DROP TABLE等。
● 数据操纵语言(DML,Data Manipulation Language):用来操纵数据库中的数据的命令,如SELECT、INSERT、UPDATE、DELETE、CURSOR等。
● 数据控制语言(DCL,Data Co ntrol Langu age):用来控制数据库组件的存取许可、存取权限等的命令,如GRANT\REVOKE等。
● 流程控制语言(Flow Control Language):用于设计应用程序的语句,如IF、WHILE、CASE等。
● 内嵌函数:嵌于命令中使用的标准函数。
● 其他命令。
4.1.1 T -SQL语言的具体组成
T-SQL语句数目、种类较多,其主体大约由40条语句组成,如表4.1所示。
表4.1 基本的T-SQL语句
4.1.2 T -SQL语言的结构
所有的SQL语句均有自己的格式,每条SQL语句均由一个谓词(Verb)开始。该谓词描述这条语句要产生的动作,如图4.1所示的SELECT关键字。谓词后紧接着一个或多个子句(Clause)。子句中给出了被谓词作用的数据或提供谓词动作的详细信息。每一条子句由一个关键字开始,如图4.1所示的WHERE。
图4.1 SQL语句的结构
4.1.3 常用的T-SQL语句
在使用数据库时,用得最多的是数据操纵语言(Data Manipulation Language)。DML包含了最常用的核心SQL语句,即SELECT、INSERT、UPDATE、DELETE。下面对以后章节中经常用到的SELECT语句作简单介绍。
SELECT语句的语法如下:
SELECT [ALL|DISTINCT]<目标表达式>[,<目标表达式>]… FROM<表或视图名>[,<表或视图名>]… [WHERE<条件表达式>] [GROUPBY<列名1> [HAVING<条件表达式>]] [ORDERBY<列名2> [ASC|DESC]]
整个SELECT语句的含义是:根据WHERE子句的条件表达式,从FROM子句指定的基本表或视图中找出满足条件的元素组,再按SELECT子句中的目标列表达式选出元素组中的属性值形成结果表。
如果有GROUP子句,则将结果按<列名1>的值进行分组,该属性列值相等的元素组为一个组,每个组产生结果表中的一条记录。如果GROUP子句带有HAVING短语,则只有满足指定条件的组才予以输出。如果有ORDER子句,则结果表还要按<列2>的值升序或降序排序。在第7章中将对SELECT语句的常用形式进行详细的讨论。
4.2 数据类型
和标准SQL语言一样,T-SQL中也包含大量的数据类型。本章将对主要的数据类型进行学习。
4.2.1 整数数据类型
整数数据类型是最常用的数据类型之一,具体包括以下几种类型。
1.INT(INTEGER)数据类型
INT(或INTEGER)数据类型存储从-231(-2,147,483,648)到231-1(2,147,483,647)之间的所有正负整数。每个INT类型的数据按4个字节存储,其中1位表示整数值的正负号,其他31位表示整数值的长度和大小。
2.SMALL INT数据类型
SMALL INT数据类型存储从-215(-32,768)到215-1(32,767)之间的所有正负整数。每个SMALL INT类型的数据占用2个字节的存储空间。其中,1位表示整数值的正负号,其他15位表示整数值的长度和大小。
3.TINY INT数据类型
TINY INT数据类型存储从0到255之间的所有正整数。每个TINY INT类型的数据占用1个字节的存储空间。
4.BIG INT数据类型
BIG INT数据类型存储从-263(-9,223,372,036,854,775,807)到2 63-1(9,223,372, 036,854,775,807)之间的所有正负整数。每个BIG INT类型的数据占用8个字节的存储空间。
● 在数据类型优先表中,BIG INT数据类型位于INT之上、SMALLMONEY之下。
● SQL Server不能自动把INT型数据转换成BIG INT型。
● 如果函数的参数表达式是一个BIG INT类型时,函数只能返回BIG INT类型的数据。使用BIG INT数据类型的函数有AVG、CEILING、FLOOR、MAX、MIN、ROUND及SUM等。
● 在指定了整型数据的所有语法位置使用BIG INT数据类型的有ALTER PROCEDURE、ALTER TABLE、CREATE PROCEDURE、CREATE TABLE及DECLARE变量。
4.2.2 二进制数据类型
二进制数据类型是比较常用的数据类型之一,具体包括以下两种类型。
1.BINARY数据类型
BINARY数据类型用于存储二进制数据。其定义形式为BINARY(n),n表示数据的长度,取值为1~8000。在使用时必须指定BINARY类型数据的大小,至少应为1个字节。BINARY类型数据占用n+4个字节的存储空间。在输入数据时必须在数据前加上字符“0X”作为二进制标识。例如,要输入“abc”则应输入“0Xabc”。若输入的数据过长,将会截掉其超出部分。若输入的数据位数为奇数,则会在起始符号“0X”后添加一个0,如上述的“0Xabc”会被系统自动变为“0X0abc”。
2.VAR BINARY数据类型
VAR BINARY数据类型的定义形式为VAR BINARY(n)。它与BINARY类型相似,n的取值也为1~8000。若输入的数据过长,将会截掉其超出部分。不同的是VAR BINARY数据类型具有变动长度的特性,因为VAR BINARY数据类型的存储长度为实际数值长度+4个字节。当BINARY数据类型允许NULL值时,将被视为VARBINARY数据类型。一般情况下,由于BINARY数据类型长度固定,因此它比VARBINARY类型的处理速度快。
4.2.3 浮点数据类型
浮点数据类型用于存储十进制小数。浮点数值的数据在SQL Server 2008中采用上舍入(Round u p,或称为只入不舍)方式进行存储。所谓上舍入是指,当(且仅当)要舍入的数是一个非零数时,对其保留数字部分的最低有效位上的数值加1,并进行必要的进位。若一个数是上舍入数,其绝对值不会减少。例如,对3.14159265358979分别进行2位和12位舍入,结果为3.15和3.141592653590。
1.REAL数据类型
REAL数据类型可精确到第7位小数,其范围为从-3.40E-38到3.40E+38。每个REAL类型的数据占用4个字节的存储空间。
2.FLOAT数据类型
FLOAT数据类型可精确到第15位小数,其范围为从-1.79E-308到1.79E+308。每个FLOAT类型的数据占用8个字节的存储空间。FLOAT数据类型可写为FLOAT (n)的形式。n指定FLOAT数据的精度。n为1~15之间的整数值。当n取1~7时,实际上是定义了一个REAL类型的数据,系统用4个字节存储它;当n取8~15时,系统认为其是FLOAT类型,用8个字节存储它。
3.NUMERIC数据类型
NUMERIC数据类型与DECIMAL数据类型完全相同。
4.DECIMAL数据类型
DECIMAL数据类型可以提供小数所需要的实际存储空间,但也有一定的限制,可以用2到17个字节来存储从-1038-1到1038-1之间的数值。可将其写为DECIMAL[(p,[s])]的形式,p和s确定了精确的比例和数位。其中p表示可供存储的值的总位数(不包括小数点),默认值为18;s表示小数点后的位数,默认值为0。例如,decimal(15,5),表示共有15位数,其中整数10位,小数5位。表4.2列出了各精确度所需的字节数之间的关系。
表4.2 DE CIMAL数据类型的精度与字节数
4.2.4 逻辑数据类型
逻辑数据类型BIT占用1个字节的存储空间,其值为0或1。如果输入0或1以外的值,将被视为l。BIT类型不能定义为NULL值(所谓NULL值是指空值或无意义的值)。
4.2.5 字符数据类型
字符数据类型是使用最多的数据类型。它可以用来存储各种字母、数字符号、特殊符号。一般情况下,使用字符类型数据时须在其前后加上单引号(’)或双引号(”)。
1.CHAR数据类型
CHAR数据类型的定义形式为CHAR[(n)]。以CHAR类型存储的每个字符和符号占一个字节的存储空间。n表示所有字符所占的存储空间,n的取值为1~8000,即可容纳8000个ANSI字符。若不指定n值,则系统默认值为1。若输入数据的字符数小于n,则系统自动在其后添加空格来填满设定好的空间。若输入的数据过长,将会截掉其超出部分。
2.NCHAR数据类型
NCHAR数据类型的定义形式为NCHAR[(n)]。它与CHAR类型相似,不同的是NCHAR数据类型n的取值为1~4000。因为NCHAR类型采用UNICODE标准字符集(Character Set),UNICODE标准规定每个字符占用两个字节的存储空间,所以它比非UNICODE标准的数据类型多占用一倍的存储空间。
使用UNICODE标准的好处是因其使用两个字节做存储单位,单个存储单位的容纳量大大增加了,可以将全世界的语言文字都囊括在内,在一个数据列中就可以同时出现中文、英文、法文、德文等,而不会出现编码冲突。
3.VARCHAR数据类型
VARCHAR数据类型的定义形式为VARCHAR[(n)]。它与CHAR类型相似,n的取值也为1~8000,若输入的数据过长,将会截掉其超出部分。不同的是,VARCHAR数据类型具有变动长度的特性,因为VARCHAR数据类型的存储长度为实际数值长度,若输入数据的字符数小于n,则系统不会在其后添加空格来填满设定好的空间。一般情况下,由于CHAR数据类型长度固定,因此它比VARCHAR类型的处理速度快。
4.NVARCHAR数据类型
NVARCHAR数据类型的定义形式为NVARCHAR[(n)]。它与VARCHAR类型相似。不同的是,NVARCHAR数据类型采用UNICODE标准字符集(Character Set),n的取值为1~40000。
4.2.6 日期和时间数据类型
T-SQL包括如下几种日期和时间类型。
1.DATETIME数据类型
DATETIME数据类型用于存储日期和时间的结合体。它可以存储从公元1753年1月1日零时起到公元9999年12月31日23时59分59秒之间的所有日期和时间。其精确度可达三百分之一秒,即3.33毫秒。
DATETIME数据类型所占用的存储空间为8个字节。其中,前4个字节用于存储1900年1月1日以前或以后的天数,数值分正负,正数表示在此日期之后的日期,负数表示在此日期之前的日期。后4个字节用于存储从此日零时起所指定的时间经过的毫秒数。如果在输入数据时省略了时间部分,则系统将12:00:00:000AM作为时间默认值;如果省略了日期部分,则系统将1900年1月1日作为日期默认值。
2.SMALLDATETIME数据类型
SMALLDATETIME数据类型与DATETIME数据类型相似,但其日期时间范围较小,为从1900年1月1日到2079年6月6日,精度较低,只能精确到分钟,其分钟个位上为根据秒数四舍五入的值,即以30秒为界四舍五入。例如,DATETIME时间为14:38:30.283时,SMALLDATETIME认为是14:39:00。SMALLDATETIME数据类型使用4个字节存储数据。其中前两个字节存储从基础日期1900年1月1日以来的天数,后两个字节存储此日零时起所指定的时间经过的分钟数。
此外,SQL Server 2008新增了4种日期与时间相关的数据类型,如下所述。
3.DATE数据类型
在SQL Server 2005及以前的版本中,没有专门只用来存储日期(不包括时间)的特定数据类型,只能使用DATETIME或SMALLDATETIME数据类型来完成此操作。但是,当你输入日期之后,会显示还有一个时间的部分需要输入,其初始显示为12:00 A M。如果只想在输出结果中显示日期那一部分,就必须修改输出格式。
大部分情况下,可以使用getdate()函数来存储当前日期。要在SQL Server 2005中的SMALLDATETIME或DATETIME列中保存getdate()的函数值,同时也会保存了当前的时间,而这可能会引发很多问题。例如,在只需要日期作为查询条件的情况下,如果包含日期和具体时间,将有可能引发查询的错误。DATE数据类型的取值范围为0001-01-01~9999-12-31。
4.TIME数据类型
就像日期数据类型一样,如果只想存储时间数据而不需要日期部分就可以利用TIME数据类型。其取值范围为00:00:00.0000000~23:59:59.9999999。
5.DATETIME2数据类型
新的DATETIME2数据类型也是一种数据时间混合的数据类型,不过其时间部分秒数的小数部分可以保留不同位数的值,比原来的DATETIME数据类型取值范围要广。用户可以根据自己的需要通过设置不同的参数来设定小数位数,最高可以设到小数点后7位(参数为7),也可以不要小数部分(参数为0),以此类推。
6.DATETIMEOFFSET数据类型
如果把日期和时间数据保存在一列里,是不会提示该日期和时间属于哪一个时区的。时区的提示非常重要,特别是当用户处理数据包含了多个不同时区的国家时。新的DATETIMEOFFSET数据类型可以定义一个日期和时间组合,其中时间以24小时制显示,并带有时区提示。
下面介绍日期和时间的输入格式。日期的输入格式很多,大致可分为以下3类。
1.英文+数字格式
此类格式中,月份可用英文全名或缩写,日不区分大小写;年和月日之间不用逗号。年份可为4位或2位,当其为两位时,若值小于50则视为20xx年,若大于或等于50则视为19xx年;若日部分省略,则视为当月的1号。以下格式均为正确的日期格式:
June212010 Oct 120099 January 2010 2010 February 2010May 1 2010 1 Sep 99 June July 10
2.数字+分隔符格式
T-SQL允许把斜杠(/)、连接符(-)和小数点(.)作为用数字表示的年、月、日之间的分隔符。如下所示通过斜杠、连接符和小数点分别表示2010年6月22日。
YMD: 2010/6/22 2010-6-22 2010.6.22 MDY: 3/5/2010 3-5-2010 3.5.2010 DMY: 31/12/2009 31-12-2009 31.12.2010
3.纯数字格式
纯数字格式是以连续的4位、6位或8位数字来表示日期。如果输入的是6位或8位数字,系统将按年、月、日来识别,即YMD格式,并且月和日都是用两位数字来表示。
如果输入的数字是4位数,系统认为这4位数代表年份,其月份和日默认为此年度的1月1日。如下所示T-SQL将20100601识别为2010年6月1日:
20100601---2010年6月1日 091212---2009年12月12日 2 08---2008年
在输入时间时必须按“小时、分钟、秒、毫秒”的顺序来输入,在其间用冒号(:)隔开。但可将毫秒部分用小数点“.”分隔,其后第一位数字代表十分之一秒,第二位数字代表百分之一秒,第三位数字代表千分之一秒。当使用12小时制时,用AM(am)和PM(pm)分别指定时间是午前或午后,若不指定,系统默认为AM。AM与PM均不区分大小写。如3:5:下2pm表示下午3时5分7秒200毫秒。
3:5:7.2pm—下午3时5分7秒200毫秒 10:23:5.123Am—上午10时23分5秒123毫秒
可以使用SET DATEFORMAT命令来设定系统默认的日期和时间格式。
4.2.7 货币数据类型
货币数据类型用于存储货币值。在使用货币数据类型时,应在数据前加上货币符号,系统才能辨识其为哪国的货币。如果不加货币符号,则默认为¥。
1.MONEY数据类型
MONEY数据类型的数据是一个有4位小数的DECIMAL值,其取值为–263(-922,337,203,685,477.5808)~263 – 1(+922,337,203,685,477.5807),数据精度为万分之一货币单位。MONEY数据类型使用8个字节存储。
2.SMALLMONEY数据类型
SMALLMONEY数据类型类似于MONEY类型,但其存储的货币值范围比MONEY数据类型小。其取值为-214, 748.3648~+214, 748.3647,存储空间为4个字节。
4.2.8 文本和图形数据类型
这类数据类型用于存储大量的字符或二进制数据。
1.TEXT数据类型
TEXT数据类型用于存储大量文本数据,其容量理论上为1~231-1(2,147,483,647)个字节,在实际应用时需要视硬盘的存储空间而定。TEXT和IMAGE类型的数据直接存放到表的数据行中,而不是存放到不同的数据页中。这就减少了用于存储TEXT和IMAGE类型的空间,并相应减少了磁盘处理这类数据的I/O数量。
2.NTEXT数据类型
NTEXT数据类型与TEXT类型相似。不同的是,NTEXT类型采用UNICODE标准字符集(Character Set),因此其理论容量为230-1(1,073,741,823)个字节。
3.IMAGE数据类型
IMAGE数据类型用于存储大量的二进制数据(Binary Data),其理论容量为231-1(2,147,483,647)个字节。其存储数据的模式与TEXT数据类型相同。它通常用来存储图形等OLE(Object Linking and Embedding,对象连接和嵌入)对象。在输入数据时同BINARY数据类型一样,必须在数据前加上字符“0X”作为二进制标识。
4.2.9 其他数据类型
T-SQL中还定义了其他一些数据类型,如下所述。
1.TIMESTAMP数据类型
TIMESTAMP数据类型提供数据库范围内的唯一值。此类型相当于BINARY(8)或VARBINARY(8),但当它所定义的列在更新或插入数据行时,此列的值会被自动更新,一个计数值将自动地添加到此TIMESTAMP数据列中。每个数据库表中只能有一个TIMESTAMP数据列。如果建立一个名为TIMESTAMP的列,则该列的类型将被自动设为TIMESTAMP数据类型。
2.UNIQUEIDENTIFIER数据类型
UNIQUEIDENTIFIER数据类型存储一个16位的二进制数字。此数字称为GUID(Globally Unique Identifier),即全球唯一鉴别号。此数字是由SQL Server 2008的NEWID()函数产生的全球唯一的编码,在全球各地的计算机经由此函数产生的数字不会相同。
3.sql_variant数据类型
这是一个用得不多的数据类型,但在某些场合下,该数据类型可能很有用。它用于存储SQL Server 2008支持的各种数据类型(不包括TEXT、NTEXT、IMAGE、TIMESTAMP和sql_variant)的值。
换言之,这个类型类似于VB编程中的variant类型,或者C#里面的object类型。它可以存放很多种格式。例如,一个sql_variant列既可以存放数字,也可以存放文本。当然,正因为这样的特性,它们在读取的时候必须经过一些转换,否则不知道是什么类型。当然这种转换会有风险,也就是所谓的类型不安全。这种类型在使用上还有另外一些限制,请确认在使用之前对其进行必要的了解。
4.table数据类型
SQL Server 2008提供了一种新的用户自定义数据类型——自定义表数据类型(User-defined Table Types),用于存储对表或视图处理后的结果集。它可以作为参数提供给语句、存储过程或者函数。可以为它创建唯一约束和主键。table数据类型不适用于表中的列,而只能用于Transact-SQL变量和用户定义函数的返回值。这一类型使得变量可以存储一个表,从而使函数或过程返回查询结果更加方便快捷。
以下是代码示例:
USE AdventureWorks; GO /**//* Create a user-defined table type */ CREATE TYPE LocationTableType AS TABLE ( LocationName VARCHAR(50) , CostRate INT ); GO
对于用户自定义表类型,有如下约束:
● 用户自定义表类型不能作为表的列或者结构化用户自定义类型的域。
● 基于用户自定义表类型的别名类型。
● 不允许NOT FOR REPLICATION选项。
● CHECK约束需要一个计算列。
● 在计算列上的主键时必须包含NOT NULL和PERSISTED约束。
● 不能在用户自定义表类型上创建非簇索引。除非索引是创建PRIMARY KE Y或UNIQUE约束的返回值。
● 不能指定DEFAULT值。
● 一旦用户自定义表类型被创建,它就无法更改。
● 如果没有定义用户自定义表类型上的计算列,则用户自定义函数无法调用。
4.2.10 SQL Server 2008新增基于位置的数据类型
要存储位置数据也相当简单,只需要将位置的经纬度值存储起来即可。使用简单的浮点字段就可以存储这些信息,但依靠这种数据类型只能实现一些简单的应用,如果你想创建更高级的应用,或使用几何算法来定位数据点,则必须自己动手编写代码。例如,如何在10公里范围内快速找出所有存储的位置。因此在SQL Server 2008中,新增了基于位置的数据类型,具有地理空间特性。
1.geometry数据类型
该数据类型可以存储x和y值,并支持基于这些值的计算。geometry是基于平面进行计算的。
2.geography数据类型
geography数据类型也可以存储x和y值,并支持基于这些值的计算。但geography数据类型是基于地球的实际形状计算的,因此与geometry数据类型之间的差异实际上是很大的。
例如,计算最短路线时,基于平面的计算结果和基于圆的计算结果可能相差很大。以航线为例,两站之间基于平面的距离和基于圆的距离可能相差十万八千里。实际上,SQL Server 2008可以根据多个不同的圆度和坐标进行计算。这种支持是必要的,因为不同的国家地理形状略有不同,计算方法也略有差异。如果不小心,这些差异即使很微小,最终也会影响结果。
4.3 常量与变量
Transact-SQL中可以使用常量和两种变量,一种是局部变量Local Variable,另外一种是全局变量Global Variable。
4.3.1 常量
常量,也称为文字值或标量值,是表示一个特定数据值的符号。常量的格式取决于它所表示的值的数据类型,下面给出部分常用的常量形式。
字符串常量括在单引号内并包含字母数字字符(a~z、A~Z和0~9)及特殊字符,如感叹号(!)、at符(@)和数字号(#)。将为字符串常量分配当前数据库的默认排序规则,除非使用COLLATE子句为其指定了排序规则。用户键入的字符串通过计算机的代码页计算,如有必要,将被转换为数据库的默认代码页。如果单引号中的字符串包含一个嵌入的引号,可以使用两个单引号表示嵌入的单引号。对于嵌入在双引号中的字符串则没有必要这样做。下面是字符串常量的示例:
'Cincinnati' 'Process X is 50% complete.' 'The level for job_id: %d should be between %d and %d.' "O'Brien"
二进制常量具有前辍0x并且是十六进制数字字符串。这些常量不使用引号括起。下面是二进制字符串常量的示例:
0xAE 0x12Ef 0x69048AEFDD010E 0x (empty binary string)
decimal常量由没有用引号括起来并且包含小数点的数字字符串来表示。下面是decimal常量的示例:
1894.1204 2.0
float和real常量使用科学计数法来表示。下面是float或real值的示例:
101.5E5 0.5E-2
money常量以前缀为可选的小数点和可选的货币符号的数字字符串来表示。money常量不使用引号括起。SQL Server 2008不强制采用任何种类的分组规则,例如,在代表货币的字符串中每隔3个数字插入一个逗号(,)。下面是money常量的示例:
$12 $542023.14
uniqueidentifier常量是表示GUID的字符串。可以使用字符或二进制字符串格式指定。以下示例都指定相同的GUID:
'6F9619FF-8B86-D011-B42D-00C04FC964FF' 0xff19966f868b11d0b42d00c04fc964ff
4.3.2 局部变量
局部变量是用户可自定义的变量,它的作用范围仅在程序内部。在程序中通常用来存储从表中查询到的数据,或当作程序执行过程中暂存变量使用。局部变量必须以“@”开头,而且必须先用DECLARE命令说明后才可使用。其说明形式如下:
DECLARE @变量名 变量类型[,@变量名 变量类型…]
其中,变量类型可以是SQL Server 2008支持的所有数据类型,也可以是用户自定义的数据类型。
在Transact-SQL中不能像在一般的程序语言中一样使用“变量=变量值”来给变量赋值,必须使用SELECT或SET命令来设定变量的值。其语法如下:
SELECT@局部变量=变量值 SET@局部变量=变量值
4.3.3 全局变量
全局变量是SQL Server系统内部使用的变量,其作用范围并不局限于某一程序,而是任何程序均可随时调用。全局变量通常存储一些SQL Server的配置设定值和效能统计数据,用户可在程序中用全局变量来测试系统的设定值或Transact-SQL命令执行后的状态值。
如表4.3所示为常用的SQL Server全局变量。
表4.3 常用SQL Server全局变量
4.4 注释符、运算符与通配符
和其他编程语言一样,T-SQL中也包括注释符、运算符与通配符。
4.4.1 注释符
注释是程序中不被执行的正文,主要用于对程序代码进行辅助说明。注释不参与程序的编译,不影响执行结束。还可以把程序中暂时不用的语句注释掉,使它们暂时不参与执行。等需要使用这些语句时,再将它们恢复。
在Transact-SQL中可使用两类注释符:
● ANSI标准的注释符--,用于单行注释。
● 与C语言相同的程序注释符号,即/* */,/*用于注释文字的开头,*/用于注释文字的结尾,可在程序中标识多行文字为注释。
下面的例子在创建数据库的代码中分别使用了单行注释和多行注释。
【范例4-1】
CREATE DATABASE test /*创建名为test的数据库,该数据库用于代码测试使用。 数据库的命名规则按照标识符的使用规则。*/ ON PRIMARY ( NAME= 'test', --指定建立数据库对应的逻辑名字 FILENAME='C:\Program Files\Microsoft SQL Server\MSSQL\data\test.mdf', --指定用于存放数据库部分的磁盘文件,路径必须指定为SQL Server所安装服务器上的某个文件夹 SIZE=10240KB, --指定数据库文件的初始大小,用户可以以MB为单位指定大小,也可以使用单位KB来指定大小 --当添加数据或日志文件时,其默认大小是1 MB MAXSIZE = UNLIMITED, FILEGROWTH = 10% ) GO
4.4.2 运算符
运算符用于完成基本的算术、关系等运算。
1.算术运算符
包括+(加)、-(减)、*(乘)、/(除)、%(取余)。
在Transact-SQL中,算术运算符用于在两个表达式上执行数学运算,这两个表达式可以是任何数字数据类型。以“+”运算符为例,它包含了3个方面的意义:
● 表示正号,即在数值前添加“+”号表示该数值是一个正数。
● 表示算术运算的加号,能将数值类型的两个数据相加。
● 连接两个字符型或binary型的数据,这时的“+”号叫做字符串串联运算符。
2.比较运算符
比较运算符用来测试两个表达式是否相同。除了TEXT、NTEXT或IMAGE数据类型的表达式外,比较运算符可以用于所有的表达式。比较运算符的符号及其含义如表4.4所示。
表4.4 T -SQL比较运算符
比较运算符的结果是布尔数据类型,它有3种值:TRUE、FALSE和NULL。那些返回布尔数据类型的表达式被称为布尔表达式。和其他SQL Server数据类型不同,不能将布尔数据类型指定为表列或变量的数据类型,也不能在结果集中返回布尔数据类型。
当SET ANSI_NULLS为ON时,带有一个或两个NULL表达式的运算符返回NULL。当SET ANSI_NULLS为OFF时,上述规则同样适用。在WHERE子句中使用带有布尔数据类型的表达式,可以筛选出符合搜索条件的行,也可以在流程控制语言语句(如IF和WHILE)中使用这种表达式。
3.逻辑运算符
逻辑运算符用来对某个条件进行测试,以获得其真实情况。逻辑运算符和比较运算符一样,返回带有TRUE或FALSE值的布尔数据类型。逻辑运算符的符号及其含义如表4.5所示。
表4.5 T -SQL逻辑运算符
位运算^^在两个表达式之间执行位操作,这两个表达式可以是任意两个整型数据类型的表达式。位运算符的符号及其定义,如表4.6所示。位运算符的操作数可以是整型或二进制字符串数据类型中的任何数据类型(但IMAGE数据类型除外)。此外,两个操作数不能同时是二进制字符串数据类型中的某种数据类型。
表4.6 T -SQL位运算符
4.连接运算符
连接运算符“+”用于连接两个或两个以上的字符或二进制串、列名或者串和列的混合体,将一个串加入到另一个串的末尾,其语法如下:
<expression1>+<expression2>
默认情况下,对于varchar数据类型的数据,在INSERT或赋值语句中,空的字符串将被解释为空字符串。在串联varchar、char或text数据类型的数据时,空的字符串被解释为空字符串。例如,'abc' + '' + 'def'被存储为'abcdef'。但是,如果兼容级别设置为65,则空常量将作为单个空白字符处理,'abc' + '' + 'def'将被存储为'abc def'。
5.一元运算符
一元运算符只对一个表达式执行操作。这个表达式可以是数字数据类型中的任何一种数据类型,如表4.7所示。
表4.7 T -SQL位一元运算符
4.4.3 运算符优先级
在Transact-SQL中运算符的处理顺序如下所示,如果相同层次的运算出现在一起时则处理顺序位从左到右。
● 括号。
● 位运算符~。
● 算术运算符*、/、%。
● 算术运算符+、-。
● 位运算符^。
● 位运算符&。
● 位运算符|。
● 逻辑运算符NOT。
● 逻辑运算符AND。
● 逻辑运算符OR。
4.4.4 通配符
通配符提供了用一个名称指定多个文件名或目录名的便捷方式。在搜索数据库中的数据时,SQL通配符可以替代一个或多个字符。在SQL Server 2008中可以使用如表4.8所示的通配符。
表4.8 T -SQL通配符
4.5 控制命令
我们可以通过T-SQL语言编制更为复杂的控制程序,而要完成这一任务,就需要用到各种控制命令。本节将对主要的控制命令进行学习。
4.5.1 流程控制命令
Transact-SQL语言使用的流程控制命令与常见的程序设计语言类似,主要有以下几种控制命令。
1.分支条件控制命令IF…ELSE
该命令用于对条件分支进行控制。其语法如下:
IF<条件表达式> <命令行或程序块> [ELSE [条件表达式] <命令行或程序块>]
其中,<条件表达式>可以是各种表达式的组合,但表达式的值必须是逻辑值“真”或“假”。ELSE子句是可选的,最简单的IF语句没有ELSE子句部分。IF…ELSE用来判断当某一条件成立时执行某段程序,条件不成立时执行另一段程序。如果不使用程序块,IF或ELSE只能执行一条命令。IF…ELSE可以进行嵌套。
【范例4-2】如下所示为一个使用IF…ELSE命令的范例,根据变量值大小的不同,打印不同的内容。
declare @x int, @y int, @z int select @x = 1, @y = 2, @z=3 if @x > @y print 'x > y' -打-印字符串'x > y' else if @y > @z print 'y > z' else print 'z > y'
【运行结果】
z > y
2.开始结束语句BEGIN…END
该命令用于控制语句的开始与结束。其语法如下:
BEGIN <命令行或程序块> END
BEGIN…END用来设定一个程序块,将在BEGIN…END内的所有程序视为一个单元执行。BEGIN…END经常在条件语句,如IF…ELSE中使用。在BEGIN…END中可嵌套另外的BEGIN…END来定义另一程序块。如下所示为使用BEGIN…END的例子。在BEGIN…END间的程序段完成对Person表中名叫ADAMS的人的查询,并打印完成提示。
BEGIN SELECT * from Person WHERE LastName = 'ADAMS'; PRINT 'complete' END
3.多分支控制命令CASE
CASE命令用于对多个条件分支进行控制。CASE命令有两种语句格式:
/*简单CASE形式,只将输入的运算表达式与WHEN后的表达式进行比较。 如果表达式匹配,则执行THEN的表达式*/ CASE<运算式> --任意有效的表达式 WHEN<运算式>THEN<运算式> WHEN<运算式>THEN<运算式> [ELSE<运算式>] END //复杂CASE形式,根据WHEN后的条件表达式是否为TRUE,判定THEN后的表达式是否执行 CASE WHEN<条件表达式>THEN<运算式> WHEN<条件表达式>THEN<运算式> [ELSE运<算式>] END
CASE命令可以嵌套到SQL命令中。
【范例4-3】如下所示为一个使用复杂CASE语句的例子。
use example update employee set e_wage = -设-置e_wage变量的值 case whenjob_level = ’1’ then e_wage*1.08 --如果job_level为1,则e_wage= e_wage*1.08,下同 whenjob_level = ’2’ then e_wage*1.07 whenjob_level = ’3’ then e_wage*1.06 else e_wage*1.05 --如果均不符合,则e_wage= e_wage*1.05 end
4.循环控制命令WHILE…CONTINUE…BREAK
WHILE…CONTINUE…BREAK命令用于对循环进行控制。其语法如下:
WHILE<条件表达式> BEGIN <命令行或程序块> [BREAK] -跳-出所有循环 [CONTINUE] -跳-出本次循环 [命令行或程序块] END
WHILE命令在设定的条件成立时会重复执行命令行或程序块。CONTINUE命令可以让程序跳过CONTINUE命令之后的语句,回到WHILE循环的第一行命令。BREAK命令则让程序完全跳出循环,结束WHILE命令的执行。WHILE语句也可以嵌套。
【范例4-4】下面是一个使用WHILE…CONTINUE…BREAK命令的例子。
USE pubs GO WHILE (SELECT AVG(price) FROM titles) < $30 --设定WHILE判定条件 BEGIN UPDATE titles SETprice = price * 2 --更新titles表 SELECTMAX(price) FROM titles IF (SELECT MAX(price) FROM titles) > $50 BREAK -- 如果最大值超出,退出循环 ELSE CONTIUNE --否则跳出本次循环 END PRINT 'Too much for the market to bear'
5.暂停控制命令WAITFOR
WAITFOR命令用来暂时停止程序执行,直到所设定的等待时间已过或所设定的时间已到才继续往下执行。其语法如下:
WAITFOR {DELAY<‘时间’>}TIME<‘时间’> |ERRORXEIT|PROCESSEXIT|MIRROREXIT}
其中,‘时间’必须为DATETIME类型的数据,如:'11:15:27',但不能包括日期。各关键字含义如下。
● DELAY:用来设定等待的时间,最多可达24小时。
● TIME:用来设定等待结束的时间点。
● ERROREXIT:直到处理非正常中断。
● PROCESSEXIT:直到处理正常或非正常中断。
● MIRROREXIT:直到镜像设备失败。
如下所示,等待1小时2分零3秒后才执行SELECT语句。
waitfor delay ’01:02:03’ select * from employee
等到晚上11点零8分后才执行SELECT语句。
waitfor time ’23:08:00’ select * from employee
6.转向命令GOTO
GOTO命令用来改变程序执行的流程,使程序跳到标有标识符的指定的程序行再继续往下执行。其语法如下:
GoTo标识符
作为跳转目标的标识符可为数字与字符的组合,但必须以“:”结尾。在GoTo命令行,标识符后不必跟“:”。
【范例4-5】如下所示为GOTO命令的例子。
declare @x int select @x = 1 label_1: print @x select @x = @x + 1 while @x < 6 goto label_1
7.返回命令RETURN
RETURN命令用于结束当前程序的执行,返回到上一个调用它的程序或其他程序。其语法如下:
RETURN([整数值])
在括号内可指定一个返回值。
【范例4-6】如下所示为返回不同程序的例子。
declare @x int, @y int select @x = 1, @y = 2 if x>y return (1) --返回程序1 else return (2) --返回程序2
4.5.2 其他常用命令
T-SQL语言还提供了其他的一些命令来帮助对数据库进行管理。
1.备份命令BACKUP
BACKUP命令用于将数据库内容或其事务处理日志备份到存储介质上(如软盘、硬盘、磁带等)。SQL Server 7.0以前的版本用的是DUMP命令来执行此功能,从SQL Server 2000起,不再使用DUMP命令。
其语法如下:
BACKUP DATABASE database --设置需要备份的数据库名 TO backup_device [,...n] --设置备份到的设备名 [WITH with_options [,...o]] --设置备份选项
2.检查点命令CHECKPOINT
CHECKPOINT命令用于将当前工作的数据库中被更改过的数据页(data page)或日志页(log page)从数据缓冲器(data buffer cache)中强制写入硬盘。
其语法如下:
CHECKPOINT
3.一致性检查命令DBCC
DBCC(Database Base Con sistency Ch ecker,数据库一致性检查程序)命令用于验证数据库完整性、查找错误、分析系统使用情况等。DBCC命令后必须加上了命令,系统才知道要做什么。例如,DBCC CHECKALLOC命令检查目前数据库内所有数据页的分配和使用情况。
4.DECLARE命令
DECLARE命令用于声明一个或多个局部变量、游标变量或表变量。在用DECLARE命令声明之后,所有的变量都被赋予初值NULL。需要用SELECT或SET命令来给变量赋值。变量类型可为系统定义的或用户定义的类型,但不能为TEXT、NTEXT、IMAGE类型。CURSOR指名变量是局部的游标变量。
其语法如下:
DECLARE {{@local_variable [AS] data_type } |{ @cursor_variable_name CURSOR } | { @table_variable_name [AS] < table_type_definition > } }[,...n] < table_type_definition > ::= TABLE ( { < column_definition > | < table_constraint > } [,...] ) < column_definition > ::= column_name { scalar_data_type | AS computed_column_expression } [COLLATE collation_name] [[DEFAULT constant_expression] | IDENTITY [( seed,increment )]] [ROWGUIDCOL] [< column_constraint >] < column_constraint > ::= {[NULL | NOT NULL] |[PRIMARY KEY | UNIQUE] |CHECK ( logical_expression ) } < table_constraint > ::= { { PRIMARY KEY | UNIQUE } ( column_name [,...] ) |CHECK ( search_condition ) }
其中,
● table_type_definition:定义表数据类型。表声明包括列定义、名称、数据类型和约束。允许的约束类型只包括PRIMARY KEY、UNIQUE、NULL和CHECK。如果类型绑定了规则或默认定义,则不能将别名数据类型用作列标量数据类型。
● @table_variable_name:table类型的变量的名称。变量名称必须以@开头,并符合有关标识符的规则。
● @local_variable:变量的名称。变量名必须以@开头。局部变量名必须符合有关标识符的规则。
● @cursor_variable_name:游标变量的名称。游标变量名称必须以@开头,并符合有关标识符的规则。
5.执行命令EXECUTE
EXECUTE命令用来执行存储过程、触发器等。其语法如下:
Functions (except inline table-valued functions), Stored Procedures, and DML Triggers { EXEC | EXECUTE } AS { CALLER | SELF | OWNER | 'user_name' }
如下所示为一个使用EXECUTE执行存储过程的例子。
USE Sales GO CREATE PROCEDURE dbo.usp_Demo --创建存储过程 WITH EXECUTE AS 'CompanyDomain\SqlUser1' --执行存储过程 AS SELECT user_name(); GO
6.终止过程命令KILL
KILL命令用于终止某一会话过程的执行。其语法如下:
KILL { session ID | UOW } [WITH STATUSONLY]
如下所示为终止会话ID为53的会话过程的执行。
KILL 53; GO
7.打印命令PRINT
PRINT命令向客户端返回一个用户自定义的信息,即显示一个字符串(最长为255个字符)、局部变量或全局变量。如果变量值不是字符串的话,必须先用数据类型转换函数CONVERT()将其转换为字符串。其中,string_expression是可返回一个字符串的表达式。表达式的长度可以超过8000个字符,但超过8000的字符将不会显示。其语法如下:
PRINT msg_str | @local_variable | string_expr
其中,
● msg_str:字符串或Unicode字符串常量。
● @local_variable:任何有效的字符数据类型的变量。@local_variable的数据类型必须为char、nchar、varchar或nvarchar,或者必须能够隐式转换为这些数据类型。
● string_expr:返回字符串的表达式。可包括串联的文字值、函数和变量。
8.抛错命令RAISERROR
RAISERROR命令用于在SQL Server系统返回错误信息时,同时返回用户指定的信息。
9.读数据命令READTEXT
READTEXT命令用于从数据类型为TEXT、NTEXT或IMAGE的列中读取数据。命令从偏移位置offset+l个字符起读取size个字符,如果size为0,则会读取4KB的数据。READTEXT命令语法如下:
READTEXT { table.column text_ptr offset size } [HOLDLOCK]
其中,
● table.column:要对其执行读取操作的表和列的名称。表和列的名称必须符合标识符规则,必须指定表名和列名。但是,可根据需要指定数据库名称和数据库所有者名称。
● text_ptr:有效的文本指针。text_ptr必须是binary(16)。
● offset:开始读取text、image或ntext数据之前,要跳过的字节数(使用text或image数据类型时)或字符数(使用ntext数据类型时)。
● size:要读取的字节数(使用text或image数据类型时)或字符数(使用ntext数据类型时)。如果size为0,则读取4KB数据。
● HOLDLOCK:使文本值被锁定以进行读取,直到事务结束为止。其他用户可读取该值,但不能对其进行修改。
除了上述这些命令之外,Transact-SQL还包括大量的应用命令,如ALTER系列语句等,还包括各式各样的应用函数,这些内容将在后面的章节中逐一介绍。
4.6 小结
本章介绍了Transact-SQL语言的基本概念及其使用方法。本章的重点是T-SQL数据类型的掌握和T-SQL语言的基本构成,本章的难点在于T-SQL的流程控制语句掌握。下章将对结合Transact-SQL语言对数据表的创建和管理进行详细的讨论。
4.7 习题
【题目1】创建一个@myvar变量,然后将一个字符串值放在变量中,最后输出@myvar变量的值。
【分析】本题考查的是变量的使用方法。首先需要通过DECLARE语句对变量进行声明,注意变量包含的字符的多少,接下来要通过SET语句完成对变量的字符串赋值。最后要注意,变量的输出方法也通过SELECT语句完成。
【核心代码】按照以上分析,构建以下核心代码:
DECLARE @myvar char(20) SET @myvar = 'This is a test' SELECT @myvar GO
【题目2】通过查询给变量赋值,获得adventureworks数据库中employee表的行数。
【分析】本题考查的是变量的使用方法。首先需要通过DECLARE语句对变量进行声明,注意变量包含的字符的多少,接下来要通过SET语句完成对变量的字符串赋值。这里的变量赋值是通过查询来完成的(使用SELECT COUNT(*) FR OM employee查询代码获得employee表中记录的总数)。
注意:本章给出的部分核心代码涉及SQL代码的各种应用,读者可以结合第7章和第8章综合学习。
【核心代码】按照以上分析,构建以下核心代码:
USE adventureworks GO DECLARE @rows int SET @rows = (SELECT COUNT(*) FROM employee)
【题目3】使用begin...end语句在pubs数据库中查找出所有售价低于20元的商业书籍的记录,如果存在这样的记录就将这些记录打印出来,否则程序返回一定信息,并打印一份所有价格低于20元的书的列表。
【分析】本题主要考查的是begin...end语句的使用方法。通过begin...end将处理逻辑包含在流程内,下面的代码给出了示例的处理逻辑。首先要注意变量的声明,接下来要查找符合条件的书籍(使用if(select count(price) from titles where title_id like 'BU%' and price<20)>0语句,表明存在以BU开头且价格低于20元的商业书籍),然后完成对相关书籍的查找并打印相关信息。
【核心代码】按照以上分析,构建以下核心代码:
use pubs set nocount on /*当SET NOCOUNT为ON时,不返回计数(表示受Transact-SQL语句影响的行数)。当SET NOCOUNT 为OFF时,返回计数*/ declare @msg varchar(255) if(select count(price) from titles where title_id like 'BU%' and price<20)>0 --存在符合要求的书 begin set @msg='There are several books that are a good value at under 20.these books are:' print @msg set nocount off select title from titles where price<20 end else begin set@msg='there are no books under 20.' print @msg end
【题目4】计算pubs数据库中所有书籍的平均价格。如果平均价格小于30,则所有书籍的价格变为原来的两倍,再判断平均价格的值。这样循环下去,直到书籍的平均价格大于或者等于30为止。每次循环过程中都计算一次当前书籍的最高价格,如果此价格大于50则跳出循环并打印警告信息。
【分析】本题考查的是while语句和begin...end语句的使用方法。与上一题类似,需要使用begin...end语句来包含核心处理逻辑。同时,与上一题不同的是,在begin...end语句以前需要使用while语句来设定循环判断书籍的平均价格是否小于30。
【核心代码】按照以上分析,构建以下核心代码:
use pubs go while (select avg(price) from titles)<30 begin update titles set price=price*2 /*设置价格为原来价格的两倍,从而不断进行循环,直到满足退出循环的条件*/ select max(price) from titles if(select max(price) from titles)>50 break else contineu end print 'too much for the market to bear'
【题目5】在pubs数据库中查询每个作者所居住州的全名。
【分析】本题考查的是CASE语句的使用方法,结合例子进行即可,注意对照pubs数据库中对应的数据列值的形式。
【核心代码】按照以上分析,构建以下核心代码:
SELECT au_fname, au_lname, CASE state WHEN''CA'' THEN ''California'' WHEN''KS'' THEN ''Kansas'' WHEN''TN'' THEN ''Tennessee'' WHEN''OR'' THEN ''Oregon'' WHEN''MI'' THEN ''Michigan'' WHEN''IN'' THEN ''Indiana'' WHEN''MD'' THEN ''Maryland'' WHEN''UT'' THEN ''Utah'' ENDAS StateName FROM pubs.dbo.authors
【题目6】使用学生信息数据库的学生情况数据表,查询是否有电子系的学生,有则显示:“已有电子系的学生!”,同时显示他们的记录内容;若无则显示:“尚无电子系的学生报到!”,并显示所有记录内容。
【分析】本题考查的是begin...end语句和if…else语句的使用方法。在前面的例子中我们已经看到了begin...end语句和if语句的结合,在此基础上,作为分支语句,还可以提供以else为代表的另一分支,在本例中就体现为显示不同的打印内容。
【核心代码】按照以上分析,构建以下核心代码:
use学生信息 if exists(select所在系from学生情况where所在系='电子') begin print已'有电子系的学生!' select* from学生情况where所在系='电子' end else begin print尚'无电子系的学生报到!' select* from学生情况 end
说明:表示条件分支的语句若有两个以上,则必须表示为语句块。
【题目7】求1~100的所有整数的累加和。
【分析】本题考查的是while语句和变量的使用方法。和其他语言编写这种累加问题类似,本题需要完成的逻辑就是在规定次数内实现与累加和的相加。需要注意变量的声明和变量的运算方法。
【核心代码】按照以上分析,构建以下核心代码:
Declare @n int, @s int Select @n=1,@s=0 While @n<=100 Begin Set@s=@s+ @n Set @n=@n+1 End select '1~100的累加和'=@s
【题目8】设S=1*2*3*4*5*…*N,求S不大100000时最大的N值及对应的S值。
【分析】本题考查的是while语句和if…else语句的使用方法。循环过程和上一题类似,同时注意while语句和if…else语句的嵌套顺序。
【核心代码】按照以上分析,构建以下核心代码:
Declare @i int ,@k int,@s smallint Select @i=1,@k=1,@s=1 While @s=1 begin set @k=@k*@i if @k>100000 break set@i=@i +1 end select 'N值'=@i-1 ,'S值'=@k/@i
【题目9】利用T-SQL语言编写1~100以内符合勾股定理的3个数。
【分析】第一次从1~100中取第一个数,再从1~100中取第二个数,再从1~100中取第三个数,如果第一个数的平方加上第二个数的平方等于第三个数的平方,则输出这3个数,如此循环往复。
【核心代码】按照以上分析,构建以下核心代码:
declare @a int,@b int,@c int set @a=1 while @a<=100 begin set @b=1 while @b<=100 begin set @c=1 begin while @c<=100 begin if power(@a,2)+power(@b,2)=power(@c,2) --取平方 print str(@a,3,0)+','+str(@b,3,0)+','+str(@c,3,0) set @c=@c+1 end end set @b=@b+1 end set @a=@a+1 end
注意:最内层循环每执行一次变量@c加1,循环结束后,@c重新赋值为1,同时第二层循环的值加1,再回到内层循环测试,第二层循环测试结束后,最外层循环再加1。如此循环往复,最内层循环每找到这一组数后,即输出显示。
【题目10】求最大公约数和最小公倍数。
【分析】按照最大公约数和最小公倍数的实现算法来执行,使用while语句。注意中间变量的设置和循环进出的控制。
【核心代码】按照以上分析,构建以下核心代码:
DECLARE @a int,@b int,@c int,@d int SET @a=15 SET @b=9 SET @c=@a%@b SET @d=@a*@b WHILE @c!=0 BEGIN SET @a=@b SET @b=@c SET @c=@a%@b IF @c=0 BREAK ELSE CONTINEU END SELECT @b,@d/@b GO
【题目11】使用T-SQL利用流程控制语句对10以内的偶数求和,即求出2+4+6+8+10的和。
【分析】使用while语句找出相应的偶数,并进行累加求和。累加求和的方法与前面的类似,注意偶数的获得与前文的区别,循环每次递增的阶数应设置为2。
【核心代码】按照以上分析,构建以下核心代码:
declare @i int declare @sum int set @i=0 set @sum=0 while @i<=10 begin set @sum=@sum+@i set @i=@i+2 end select @sum
【题目12】假设有下面一个表:
有的学生选择了同时修几门课程(100,200),也有的学生只选择了一门课程(300,400,500)。选修多门课程的学生,要选择一门课程作为主修,主修flag里面写入Y。只选择一门课程的学生,主修flag为N。按照下面两个条件对这个表进行查询:
(1)只选修一门课程的人,返回那门课程的ID。
(2)选修多门课程的人,返回所选的主课程ID。
【分析】使用CASE语句进行情况的区分。根据学生选修的课程数的不同进行区分,注意根据不同的要求对返回的课程进行设定。
【核心代码】按照以上分析,构建以下核心代码:
SELECT std_id, CASE WHEN COUNT(*) = 1--只选择一门课程的学生的情况 THEN MAX(class_id) ELSE MAX(CASE WHEN main_class_flg = 'Y' THEN class_id ELSE NULL END ) END AS main_class FROM Studentclass GROUPBY std_id;
【题目13】表中有A B C三列,用SQL语句实现:当A列大于B列时选择A列,否则选择B列;当B列大于C列时选择B列,否则选择C列。
【分析】使用CASE语句进行情况的区分。将A列大于B列和B列大于C列使用CASE语句区分开来,同时在CASE语句内部通过then…else将两种不同的情况区分开。
【核心代码】按照以上分析,构建以下核心代码:
SELECT (CASE when a>b then a else b end ), (CASE when b>c then b else c end) FROM table_name
【题目14】有一张表,里面有3个字段:语文,数学,英语。其中有3条记录分别表示语文70分,数学80分,英语58分,请用一条SQL语句查询出这3条记录并按以下条件显示出来:
大于或等于80表示优秀,大于或等于60表示及格,小于60分表示不及格。
显示格式:
语文 数学 英语
及格 优秀 不及格
【分析】使用CASE语句进行情况的区分。注意,首先区分几种不同的科目,同时在不同科目中区分不同的分数段情况。
【核心代码】按照以上分析,构建以下核心代码:
select (case when语文>=80 then '优秀' when语文>=60 then '及格' else'不及格') as语文, (case when数学>=80 then '优秀' when数学>=60 then '及格' else'不及格') as数学, (case when英语>=80 then '优秀' when英语>=60 then '及格' else'不及格') as英语, from table