Transact-SQL语言

文章目录

概述

SQL(Structure Query Language)是结构化查询语言,是标准数据库语言.而Transact-SQL是微软公司为了其设计的数据库–SQL server而推出的一个基于SQL的变种语言.

之前我们已经接触了该语言的一些语法,接下来我们就针对该语言的一些细节语法进行说明.

数据类型

在学习任何高级语言之前,我都喜欢先看看该语言支持什么数据类型.毕竟编程就是对数据的加工处理,将输入转化为输出的过程.下面将从6各方面介绍T-SQL的数据类型.

1.整数数据类型

SQL server中一共有4中整数类型,其区别如下表:

数据类型范围所占字节数
TINYINT[0,255]1
SMALLINT[-215,215-1]2
INT[-231,231-1]4
BIGINT[-263,263-1]8

2.DECIMAL和NUMERIC

这两种数据类型都是带精度和固定位数的实数数据类型,它们在SQL server系统中被当做同一个类型处理,除了名字不一样以外,其实是完全等价的.下面只介绍DECIMAL类型的使用方式:

DECIMAL (p,s); -> p表示数字的精度,s表示数字的小数位数.

  • 精度p的取值范围是: p ∈ \in [1,38],小数位数s的取值范围是: s ∈ \in [0,p].
  • DECIMAL类型的取值范围: [-1038+1,1038-1],且DECIMAL所占字节数是变化的.
  • 若s == 0,则该实数可以当做整数类型处理.

3.MONEY和SMALLMONEY

这两种是表示货币数值的数据类型.它们的对比如下:

数据类型范围所占字节数
MONEY[-922 337 203 685 477.5808,922 337 203 685 477.5807]8
SMALLMONEY[-214 748.3648,214 748.3647]4

MONEYSMALLMONEY都是确定型数据类型,它们的精度和小数位都是固定的.但它们也有区别于其他数据类型的一些地方:

  • 它们代表货币数值,因此可以在前面加上货币单位,如$、¥.
  • 它们的小数位最多为4,超过则自动按4舍5入处理.

注意: 虽然这两种数据类型可以添加货币单位,但它们并不存这类单位,只是保存货币数值!

4.FLOAT和REAL

用于表示浮点数值数据的大致数值数据类型.浮点数据为近似值.因此,并非数据类型范围内的所有值都能精确地表示.

FLOAT(n)语法:

其中n为用于存储FLOAT数值尾数的位数(以科学记数法表示),因此可以确定精度和存储大小.如果指定了n,则n ∈ \in [1,53].n的默认值为53.

n精度所占字节数
1-247位数4
25-5315位数8

SQL Server将n视为下列两个可能值之一:

如果1 ≤ \le n ≤ \le 24,将n视为24;

如果25 ≤ \le n ≤ \le 53,将n视为53.

FLOAT(n)REAL的范围:

数据类型范围所占字节数
FLOAT(n)[-1.79E+308,-2.23E-308]、0 、[2.23E-308,1.79E+308]取决于n的值
REAL[-3.40E+38,-1.18E-38]、0 、[1.18E-38,3.40E+38]4

5.BIT

BIT是可以取值为 1、0 或 NULL 的 integer 数据类型.SQL Server数据库引擎可优化BIT列的存储:

  • 如果表中的BIT ≤ \le 8列,则这些列作为1个字节存储.如果BIT列为9到16列,则这些列作为2个字节存储,以此类推.

BIT的特点:

  • 字符串值TRUEFALSE可转换为BIT值: TRUE转换为1,FALSE转换为0.
  • 转换为BIT会将任何非零值升为1.

6.字符串类型

SQL server为字符串提供了4种类型:

CHARVARCHARTEXTNCHARNVARCHARNTEXT

接下来我们开始两两对比:

CHARVARCHAR:

CHAR(n): 固定长度字符串数据.n用于定义字符串长度(以字节为单位),且n ∈ \in [1,8000].

  • 对于单字节编码字符集(如拉丁文),存储大小为n个字节,并且可存储的字符数也为n.
  • 对于多字节编码字符集,存储大小仍为n个字节,但可存储的字符数可能小于n.

VARCHAR(n|MAX): 可变长度字符串数据.n用于定义字符串长度(以字节为单位),且n ∈ \in [1,8000].

  • MAX指示最大存储大小是 231-1个字节(2GB).
  • 对于单字节编码字符集(如拉丁文),存储大小为n+2个字节,并且可存储的字符数也为n.
  • 对于多字节编码字符集,存储大小仍为n+2个字节,但可存储的字符数可能小于n.

NCHARNVARCHAR:

NCHAR(n): 固定长度字符串数据.n用于定义字符串长度(以双字节为单位),且n ∈ \in [1,4000].

  • 存储大小为n字节的两倍.
  • 对于UCS-2编码,存储大小为n个字节的两倍,并且可存储的字符数也为n.
  • 对于UTF-16编码,存储大小仍为n个字节的两倍,但可存储的字符数可能小于n.

NVARCHAR(n|MAX): 可变长度字符串数据.n用于定义字符串长度(以双字节为单位),且n ∈ \in [1,4000].

  • 存储大小为n字节的两倍,MAX指示最大存储大小是230-1个字符(2GB).
  • 对于UCS-2编码,存储大小为n个字节的两倍+2个字节,并且可存储的字符数也为n.
  • 对于UTF-16编码,存储大小仍为n个字节的两倍+2个字节,但可存储的字符数可能小于n.

数据类型的特点以及选择数据类型是的考虑因素:

  • 如果该列数据长度都差不多相同,则应该使用CHAR(n)NCHAR(n).
  • 如果该列数据长度相差较大,则应该使用VARCHAR(n)NVARCHAR(n).
  • 如果该列数据长度不一定相同,但是相差又不是很大,则:
  1. 希望优化查询效率,则应该使用CHAR(n)NCHAR(n).
  2. 希望优化存储空间,则则应该使用VARCHAR(n)NVARCHAR(n).
  • 字符串是纯英文字符组成的,则应该使用CHAR(n)VARCHAR(n).
  • 字符串含有多国国家(含非英文字符)语言,则应该使用Unicode编码,选用NCHAR(n)NVARCHAR(n).

字符串的两种格式:

  • 对于纯英文字符组成的字符串,用单引号扩起来,若字符串本身含有一个单引号,则用一个双引号代替,如:

It’s me. -> ‘It ‘‘s me.’

  • 对于Unicode编码的字符串,在纯英文字符串表示法的基础上前面加一个N,如:

N’《Linux命令行大全》是一本面向全体Linux学习者的优秀参考书’

超长字符串(文本串):

以前的SQL server存在TEXTNTEXT类型,用于保存文本串,然而现在已经取消这两种数据类型.

根据编码不同,我们使用VARCHAR(MAX)NVARCHAR(MAX)来保存长文本串.

7.日期和时间类型

SQL server中有时间和日期这个类型,一共有如下6种:

DATETIMESMALLDATETIMEDATETIMEDATETIME2DATETIMEOFFSET.

先说一下日期和时间的格式:

  • 支持使用 ‘-’, ‘/’ 或 ‘.’ 分隔年月日.
  • 支持2字符表示的年份和4字符表示的年份,但有所区别:

2字符表示年份,当数据库默认语言为英语时,采用的默认格式是: mdy. 即:

12/21/90 <=> 12-21-90 <=> 12.21.90 <=> 1990年12月21日.

4字符表示年份,则是使用 YYYY/MM/DD 或 YYYY-MM-DD 或 YYYY.MM.DD 的格式,比较符合国人习惯.

  • 还可以使用英文常用表示法表示日期,如:

May 12 2019 <=> 12 May 201

  • 还可以使用SET LANGUAGESET DATEFORMAT来设置默认语言和时间格式,支持的时间格式有:

mdy、ymd、dmy、dym、ydm

  • 时间的表示没有什么好说的,就是正常的 -> hh:mm:ss(.fractional seconds)(AM/PM),如:

11:50:00 <=> 11:50:00 AM

DATETIMESMALLDATETIME:

这两种数据类型都可以同时表示日期和时间,差异在于表示的范围不同,对比如下:

数据类型范围精度
DATETIME1753-01-01 – 9999-12-313.33ms
SMALLDATETIME1900-01-01 – 2079-12-311min

DATETIME2:和DATETIME不同的是,DATETIME2的精确度是100ns,精度更高.

DATETIME:

DATE只能表示日期,可接受的字符串格式在前面讲过了.

TIME只能表示时间,同样格式在前面有提及.

DATETIMEOFFSET:

用于定义一个与采用24小时制并可识别时区的一日内的时间和日期.其实也就是DATETIME+时区偏移量,如:

DATETIME可接受的字符串格式:

ISO 8601描述
YYYY-MM-DDThh:mm:ss(.nnnnnnn)((+|-)hh:mm])这两种格式不受SET LANGUAGESET DATEFORMAT会话的区域设置的影响. datetimeoffset 和 datetime 部分之间不允许有空格。
YYYY-MM-DDThh:mm:ss[.nnnnnnn]Z (UTC)这种遵从ISO定义的格式表明DATETIME部分应采用协调世界时(UTC)表示.例如,1999-12-12 12:30:30.12345 -07:00应表示为1999-12-12 19:30:30.12345Z

针对以上两种格式,分别居两个例子,具体的时间表示法可以上网查找科学时间表示法:

2007-05-08 12:35:29. 1234567 +12:15

1999-12-12 19:30:30.12345Z

8.二进制类型

SQL server提供2中二进制数据类型:

BINARYVARBINARYIMAGE.

和字符串类型一样,这两种数据类型有很鲜明的特点:

  • BINARY(n): 长度为n字节的固定长度二进制数据,其中n ∈ \in [1,8000].存储大小为n字节.
  • VARBINARY(n|MAX): 可变长度二进制数据,其中n ∈ \in [1,8000].MAX指示最大存储大小是231-1个字节.存储大小为所输入数据的实际长度+2个字节.所输入数据的长度可以是0字节.

原来有IMAGE类型,用于存储二进制编码的图片信息,现在已经取消,微软建议使用VARBINARY(MAX)代替它.

关于这两种数据类型的用法,请看下表推荐:

数据类型何时使用
BINARY(n)列数据项的大小几乎一致
VARBINARY(n)列数据项的大小差异相当大
VARBINARY(MAX)列数据条目超出8000字节

9.其他类型

SQL_VARIANT类型:

  • SQL_VARIANT可以用在列、参数、变量和用户定义函数的返回值中.借助SQL_VARIANT,这些数据库对象可以支持其他数据类型的值.
  • 类型为SQL_VARIANT的列可能包含不同数据类型的行.
  • SQL_VARIANT的最大长度可以是8016个字节.实际基类型值的最大长度是8000个字节.
  • 对于SQL_VARIANT数据类型,必须先将它转换为其基本数据类型值,然后才能参与诸如加减这类运算.
  • 可以为 SQL_VARIANT 分配默认值. 该数据类型还可以将 NULL 作为其基础值,但是NULL值没有关联的基类型.此外,SQL_VARIANT不能使用其他 SQL_VARIANT作为其基础类型.
  • 唯一键、主键或外键可能包含类型为SQL_VARIANT的列,但是,组成指定行的键的数据值的总长度不应大于索引的最大长度.该最大长度是900个字节.
  • 一个表可以包含任意多个SQL_VARIANT列.
  • 不能在CONTAINSTABLEFREETEXTTABLE中使用 SQL_VARIANT.

TABLE类型:

  • 特殊数据类型,主要用于存储结果集以便以后继续处理.这些结果通常都是以表值函数返回的.
  • 将变量声明为TABLE类型,在其生存周期和适用范围内可以当成表来处理.
  • TABLE类型变量包含的数据很多,则会对系统性能造成很大影响.

XML类型: 用于存储XML数据类型,使其可以直接在SQL server中使用,注意单个变量大小不可超过2GB.

UNIQUEIDENTIFIER类型:

此类型是一个16字节的GUID,用于唯一区分对象,是一个全局标识符.

UNIQUEIDENTIFIER数据类型的列或局部变量可通过以下方式初始化为一个值:

  • 通过使用NEWIDNEWSEQUENTIALID函数.
  • 通过从xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx形式的字符串常量进行转换,其中,每个x都是0-9或a-f范围内的十六进制数字.例如,6F9619FF-8B86-D011-B42D-00C04FC964FF为有效的UNIQUEIDENTIFIER值.

HIERARCHYID类型: 长度可变的系统数据类型,用于表层次结构中的位置.

定义数据语言

定义数据语言(DDL)用于创建数据库和数据库对象,为数据库提供操作对象.以下是常用数据库对象:

数据库、登录名、架构、表、触发器、存储过程、视图、索引、函数、类型和用户等

数据库对象都要先定义才能使用,定义时使用的语句集合就是DDL,主要就是以下三个语句:

CREATE: 用于创建数据库和数据库对象,是一个从无到有的过程.

可以使用CREATE差UN刚建的数据库对象包括:

数据库、登录名、表、触发器、类型、用户、视图、数据库主密钥、非对称秘钥、对称秘钥、存储过程、全文目录、全文索引、索引、XML索引、关联操作、函数、聚合函数、默认值、规划、架构、架构组件、服务、维度成员、计算成员、挖掘模型、挖掘结构、分区函数、分区方案、端点、事件通知、消息类型、角色、应用程序角色、程序集、元组计算、证书、约定、凭据、队列、绑定、路由、命名集、统计直方图、多维数据集以及同义词等

注意: CREATE针对不同对象有不同的参数用法,就不在这里一一列举了.以下是一个例子:

USE Temp;
GO

CREATE USER Temp1 FROM LOGIN Temp1 WITH DEFAULT_SCHEMA = test1; --创建用户,制定默认架构;
GO

CREATE SCHEMA test1 AUTHORIZATION Temp1	--创建架构;
	CREATE TABLE PeopleInfo(NAME NCHAR(10),AGE INT); --创建表;
GO

ALTER: 用于更改数据库和数据库对象的结构.

ALTER只是改变对象的结构,对象已有的数据并不受任何影响,其操作的对象必须已经存在.

例如,对于表来说,在其中添加一个新列,删除一个列都属于对表结构的改变.以下是一个例子:

USE Temp;
GO

ALTER TABLE test1.PeopleInfo ADD SALARY INT;	--在表中新增一列;
GO

ALTER SCHEMA test	--更改架构内部结构;
	TRANSFER test1.PeopleInfo ; --转移表的所有权;
GO

注意: ALTER能改变对象的内部结构,其可操作对象的范围和CREATE一样.

DROP: 用于删除数据库和数据库对象,是一个从有到无的过程.

下面是一个例子:

USE Temp;
GO

DROP SCHEMA test1 --删除架构;
GO

DROP TABLE test.PeopleInfo;	--删除表;
GO

DROP USER Temp1;	--删除用户;
GO

注意:

  • DROP的可操作对象范围也可CREATE一样.
  • DROP不仅仅删除了对象,还删除了对象的所有内容.
  • 因为SQL server系统的限制,DROP仅能针对某些空对象才能成功操作,请稍稍留心.

数据操纵语言

数据操纵语言(DML)主要用于操纵表、视图中的数据.主要是以下三个语句:

INSERT: 用于向对象中插入数据.

以下是一个例子:

USE Temp;
GO

CREATE SCHEMA test1 AUTHORIZATION Alex	--创建架构;
	CREATE TABLE PeopleInfo(NAME NCHAR(10) NOT NULL,AGE INT NOT NULL); --创建表;
GO

INSERT INTO test1.PeopleInfo VALUES('张三',18);	--向表中插入三条数据;
INSERT INTO test1.PeopleInfo VALUES('李四',19);
INSERT INTO test1.PeopleInfo VALUES('王五',18);
GO

注意:

  • INSERT一次插入一行数据,多行插入需要多次使用INSERT语句.
  • INSERT一个常量时,常量应该遵循该类型常量的正确形式.

UPDATE: 更新对象中的数据.

UPDATE常用于纠正对象中的丢失、过时或者错误的数据.以下是一个例子:

USE Temp;
GO

UPDATE test1.PeopleInfo SET AGE = 30;	--将所有带有AGE属性的记录都更改;
GO

运行结果如下:

《Transact-SQL语言》

请看另一个例子:

USE Temp;
GO

UPDATE test1.PeopleInfo SET AGE = 30	--仅更改NAME属性为'张三'的记录的AGE属性;
	WHERE NAME = '张三';
GO

运行结果如下图:

《Transact-SQL语言》

可以看到,UPDATE有以下注意点:

  • 不指定条件,只指定更新的属性值,则默认会将所有记录的同一属性都更新.
  • 使用WHERE来指定需要更新条件记录.

DELETE: 删除对象中的数据.

以下是一个例子:

USE Temp;
GO

DELETE test1.PeopleInfo WHERE NAME = '张三'; --删除NAME属性为'张三'的记录;
GO

SELECT * FROM test1.PeopleInfo;
GO

运行结果如图:

《Transact-SQL语言》

另一个例子:

USE Temp;
GO

DELETE test1.PeopleInfo; --删除表的所有记录;
GO

SELECT * FROM test1.PeopleInfo;
GO

运行结果如图:

《Transact-SQL语言》

注意:

  • UPDATE一样,DELETE没有指定具体删除条件时,默认删除表中所有数据,请务必谨慎行事.
  • DELETE只是删除数据,对象依然存在,而DROP删除了对象,数据就不复存在了.

数据控制语言

数据控制语言(DCL)主要用来执行有关安全管理的操作.主要包括GRANTREVOKEDENY语句.

由于已经在前面介绍过了,就不再赘述,为加深印象,直接再看一个例子:

USE Temp;
GO

GRANT CREATE TABLE TO Alex WITH GRANT OPTION;	--将建表的权限和授予建表权限的权限授予Alex;
GRANT SELECT TO Alex;	--将SELECT权限授予Alex;
GO

REVOKE CREATE TABLE FROM Alex CASCADE;	--撤回Alex建表和授予建表权限的权限;
DENY SELECT TO Alex;	--否认Alex的SELECT权限;
GO

事务管理语言

事务管理语言(TML)用于显示管理事务,事务是一系列操作的集合,又称原语或原子操作,主要是以下三个语句:

  1. BEGIN TRANSACTION: 定义事务的开始.
  2. COMMIT TRANSACTION: 提交事务.
  3. ROLLBACK TRANSACTION: 事务回滚.

我们说了,事务是原子操作,是一个整体,其中操作只允许全部成功或者全不成功,其流程如下:

《Transact-SQL语言》

事务经过定义形成,之后开始执行,如果出错则需要进行回滚,否则就可以提交.下面举一个例子:

假设我们有两个账户,现在需要从001转帐6989元到账户002中,为保证转账过程不出差错,用TML来完成:
先将我们需要使用的表建立起来(保存账户编号,客户姓名,余额和操作时间的表):

USE Temp;
GO

CREATE TABLE test.AccountInfo(accountID CHAR(3),clientName VARCHAR(10),balance DECIMAL(32,2),operateTime DATE);
INSERT INTO test.AccountInfo VALUES ('001','Aaron',10000.00,GETDATE());
INSERT INTO test.AccountInfo VALUES ('002','Alex',100.00,GETDATE());
SELECT * FROM test.AccountInfo;
GO

结果如下图:

《Transact-SQL语言》

对于转账这件事情,应该分两步走: 1. 先从001账户中取出余额, 2. 存入002账户中去.事务定义如下:

USE Temp;
GO

BEGIN TRANSACTION;
UPDATE test.AccountInfo set balance = balance - 6989.00, operateTime = GETDATE()	--取出账户001中的余额;
	WHERE accountID = '001';
IF (@@ERROR = 0)										--成功取出余额;
	BEGIN
		UPDATE test.AccountInfo set balance = balance + 6989.00, operateTime = GETDATE()	--存入账户002中;
			WHERE accountID = '002'
		IF (@@ERROR = 0)									--成功存入余额,则提交事务;
			COMMIT TRANSACTION;
		ELSE
			ROLLBACK TRANSACTION;							--否则回滚;
	END
ELSE
	ROLLBACK TRANSACTION;									--取出余额失败,回滚;7y
GO

SELECT * FROM test.AccountInfo;
GO

运行结果如下:

《Transact-SQL语言》

其中,需要强调的地方有几个:

  • @@ERROR是系统变量,如果有@@ERROR = 0,则表示上一个语句成功执行,否则表示操作失败.
  • BEGINEND应成对出现,常用于块操作,作用大概相当于C语言中的大括号.

可见事务管理最关键的部分是事务逻辑,在使用时应该考虑事务划分为几个操作,操作的先后执行顺序等.

其它语言元素

因为大部分学习数据库的人都有学习其他高级语言基础,因此这一部分就当概念内容说明,仅在必要时举例.

标识符

在SQL server中,对象的名称就是标识符,关于标识符,介绍一下命名规则即可:

常规标识符的命名:

  • 首字符必须是Unicode标准定义的字符,或者是以下几个字符: ‘-’、’@’、’#’.
  • 除首字符以外的字符: 基本拉丁字符或十进制数字或首字符可使用的字符集.
  • 尽量不要使用(有时会出错,有时不会)Transact-SQL的保留字,无论大小写形式.
  • 不允许嵌入空格或其他特殊字符.

分割标识符:包含在双引号(“”)或方括号([])内的标识符称为分割标识符.

对于符合常规标识符命名法的标识符可以分割也可以不分割.但对于不符合命名法的标识符,必须进行分割.

如: myLinux 无需分割,但是 my Linux 需要分割,分割为标识符 -> “my Linux” 或 [my Linux]

何时使用分割标识符?

  1. 标识符中含有Transact-SQL保留字,如[WHERE]分割标识符.
  2. 标识符中含有非法字符,如[product[1] table]分割标识符.

使用哪种分割标识符?

双引号引起的标识符称为引用标识符,方括号扩起的标识符称为括号内的标识符.一般情况下,不允许使用引用标识符,只有当QUTED_IDENTIFIER设置为ON时,才可使用引用标识符.设置QUTED_IDENTIFIER的脚本如下:

SET QUTED_IDENTIFIER ON;	--开启QUTED_IDENTIFIER;
SET QUTED_IDENTIFIER OFF; --关闭QUTED_IDENTIFIER;

变量和常量

变量又称为局部变量,是用来保存单个某类型数据值的对象,其命名和使用规则如下:

  • 使用DECLARE语句声明变量,多个变量用逗号隔开.
  • 变量必须以’@’字符开头,应指明变量的类型和长度.
  • 定义变量时,变量名在前,类型声明在后.
  • 使用SET语句为变量赋值或使用SELECT选择列表中当前所引用的值为变量赋值.
  • 若不进行赋值,则变量的初始值为NULL.

以下是变量声明和赋值的简单例子:

USE Temp;
GO

DECLARE @a INT,@b VARCHAR(10);	--声明变量@a,@b;
SET @a = 1346798520;	--为变量@a赋值;
SELECT @b =  clientName FROM test.AccountInfo	--将表中accountID值为'001'的记录的clientName属性值赋值给变量@b;
	WHERE accountID = '001';

常量又称直接量、表面量.常量的类型取决于其值,如用单引号引起来的就是字符串常量.

注意:

  • 以两个’@‘开头的是系统的默认函数名称,不要用’@@’+字符串作为为变量标识符.
  • 以一个’#‘开头的标识符表示系统临时表或存储过程,以两个’#’开头的表示系统全局全局临时对象.

运算符

算术运算符

运算符含义
+(加)加,也可以将一个以天为单位的数字加到日期中
-(减)减,也可以从日期中减去一个以天为单位的数字
*(乘)
/ (Divide)
%(取模)返回一个除法运算的整数余数.

注意: 这些运算符使用和C语言并无两样,可能需要注意一下结果的类型: 取表达式最高优先级变量的类型.

逻辑运算符

运算符含义
ALL如果一组的比较都为TRUE,那么就为TRUE.
AND如果两个布尔表达式都为TRUE,那么就为TRUE.
ANY如果一组的比较中任何一个为TRUE,那么就为TRUE.
BETWEEN如果操作数在某个范围之内,那么就为TRUE.
EXISTS如果子查询包含一些行,那么就为TRUE.
IN如果操作数等于表达式列表中的一个,那么就为TRUE.
LIKE如果操作数与一种模式相匹配,那么就为TRUE.
NOT对任何其他布尔运算符的值取反.
OR如果两个布尔表达式中的一个为TRUE,那么就为TRUE.
SOME如果在一组比较中,有些为TRUE,那么就为 TRUE.

以下是这些运算符使用的标准格式,具体应用的就等到使用的时候再说:

scalar_expression { = | < > | ! = | > | > = | ! > | < | < = | ! < } {ALL | SOME | ANY } (subquery)

boolean_expression AND | OR boolean_expression

test_expression [NOT] BETWEEN begin_expression AND end_expression

EXISTS (subquery)

test_expression [NOT] IN (subquery | expression [1,..,n])

match_expression [NOT] LIKE pattern

[NOT] boolean_expression  

位运算符

除了按位非(~),其余都是二元运算符.

运算符位运算
&按位与,如果两个位置上的位均为1,则结果为1.如: (101)2 & (110)2 = (100)2
|按位或,如果两个位置上任意一个位置的位为1,则结果为1.如: (101)2 | (110)2 = (111)2
^按位异或,如果两个位置上数字相异,则结果为1.如: (101)2 ^ (110)2 = (011)2
~按位非,对每个位位置上的位值取反.如: ~ (101)2 = (010)2
  • 注意: 只能对整型变量/常量使用位运算.

一元运算符

只对一个表达式操作,该表达式可以是numeric数据类型类别中的任意一种.

运算符含义
-(负)返回数值表达式的负值.
+(正)返回数值表达式的正值.
~返回数字的逻辑非.

比较运算符

比较运算符是一个二元运算符,没什么好说的,如下:

运算符含义
=等于
<>不等于
>大于
>=大于或等于
<小于
<=小于或等于
!=不等于
!<不小于
!>不大于

赋值运算符

最简单的赋值运算符是 = ,它支持与一些运算符进行级联形成复合赋值运算符,具体如下:

运算符含义
+=加法赋值
-=减法赋值
*=乘法赋值
/=除法赋值
%=取模赋值
&=位与赋值
|=位或赋值
^=位异或赋值

这些复合赋值运算符直接类别C语言去理解就可以了.

运算符的优先级比较

由1~8,优先级别从高到低:

级别运算符
1~(位非)
2*(乘)、/(除)、%(取模)
3+(正)、-(负)、+(加)、+(串联)、-(减)、&(位与)、^(位异或)、|(位或)
4=、>、<、>=、<=、<>、!=、!>、!<(比较运算符)
5NOT
6AND
7ALL、ANY、BETWEEN、IN、LIKE、OR、SOME
8=(赋值)

表达式

表达式是由标识符、变量、常量、标量函数、子查询以及运算符组成的.表达式可以在多个不同的位置使用.

表达式可分为简单表达式和复杂表达式,复杂表达式可以通过两个或以上简单表达式连接起来.

使用逻辑运算符连接起来的表达式,其类型为bool值,即TRUE,FALSE,UNKNOW.

其它表达式的类型取决于其中的变量/常量的综合作用.表达式可以理解为语句,再多就没什么好说的了.

流控制语言

一般的,结构化程序设计中,程序是以线性执行的.所谓流控制,就是要调整一些语句的执行顺序,在保证整体线性执行的情况下,对特殊情况进行特殊处理,常用的流控制语句如下:

流控制语句描述
BEGIN…END定义语句块,一个语句块为一组代码,允许语句块嵌套.
BREAK跳出WHILE循环,注意BREAK只可跳出一层循环.
GOTO使得Transact-SQL跳转至指定标签的语句执行,应避免使用GOTO.
CONTINUE忽略CONTINUE后面的语句,开始一个新的WHILE循环,
IF…ELSE分支结构,可以指定两个条件进行程序分支.
WHILE循环结构,当循环条件为TRUE时,一直执行循环体内的代码.
RETURN无条件终止查询、批处理或存储过程的执行,可以使用该语句指定返回给应用程序、批处理或存储过程的整数值.若未指定返回值,则存储过程默认返回0.
WAITFOR挂起批处理、存储过程或事务的执行,直到已超过时间间隔/达到指定等待时间/指定的RECEIVE语句至少修改一行数据才唤醒.
THROW引发异常,并将执行转移到TRY…CATCH构造的CATCH块.
TRY…CATCH类似Java的异常处理,可以通过TRY…CATCH来识别一些错误.

下面是一个例子:

USE AdventureWorks2017;
GO

WHILE ((SELECT AVG(ListPrice) FROM Production.Product) < 500)	--表中列的平均值 < 500,执行WHILE;
	BEGIN	--块开始;
		UPDATE Production.Product
			SET ListPrice += 500;
		IF (5000 < ANY(SELECT ListPrice FROM Production.Product))	--列中任意数值 > 5000,退出WHILE;
			BREAK;
		ELSE
			CONTINUE;	--否则继续WHILE;
	END		--块结束;
GO

关于THROWTRY CATCH,通常用于错误处理,需要讲几个常用的错误函数:

函数名描述
ERROR_NUMBER()返回错误的错误号
ERROR_MESSAGE()返回错误的消息文本
ERROR_SEVERITY()在发生错误的位置返回错误的严重性值
ERROR_STATE()返回导致TRY…CATCH构造的CATCH块运行的错误状态号.
ERROR_LINE()返回出现错误的行号
ERROR_PROCEDURE()返回出现错误的存储过程或触发器的名称

下面是TRY…CATCH使用的一个例子:

BEGIN TRY
	SELECT 5/0 -- 以 0 为除数的错误
END TRY
BEGIN CATCH -- 处理错误逻辑
	SELECT 
		ERROR_NUMBER() AS N'错误号',
		ERROR_SEVERITY() AS N'错误严重等级',
		ERROR_STATE() AS N'错误状态',
		ERROR_PROCEDURE() AS N'错误的过程名称',
		ERROR_LINE() AS N'产生错误的行号',
		ERROR_MESSAGE() AS N'错误消息文本'
END CATCH
GO

结果如图:

《Transact-SQL语言》

再补充一个系统变量@@ERROR,这个变量的作用是:

返回执行的上一个Transact-SQL语句的错误号.

如果前一个Transact-SQL语句执行没有错误,则返回0.

任何非0的返回值都表示前一个Transact-SQL语句执行有错误.

以下是一个简单例子:

USE AdventureWorks2017
SELECT * FROM not_found_table
GO
SELECT @@ERROR AS N'第一个错误号'
GO
SELECT 5 + 6 AS N'两个数之和'
GO
SELECT @@ERROR AS N'第二个错误号'
GO

运行结果如下(第一个与具有错误,第二个语句没有错误(返回0)):

《Transact-SQL语言》

注意: 返回的是前一个语句的错误号,如果隔得太远@@ERROR就不起作用了.

关于THROW的用法可以点这里看看: THROW,就不再展开叙述了.

注释

所有可读性强的程序都会带有注释,学过Java的都知道Java有单行注释、多行注释和文档注释三种注释.

而Transact-SQL语言中,有两种注释: 单行注释和多行注释,其语法见下面的示例即可:

USE AdventureWorks2017;		--这是一行单行注释;
GO

/* * 这里是多行注释 * 下面的语句要查询AdventureWorks2017的Person架构下的Address表的所有内容; */

SELECT * FROM Person.Address;
GO

内置函数

SQL server总有许多的内置函数,这些函数可以完成许多特定操作,大大提高系统的易用性.

函数的特点和类型

SQL server的内置函数可分为14种类型,每一种类型的内置函数都可以完成某种类型的操作,对应如下:

函数类型描述
聚合函数将多个数值合并为一个,如求和函数
配置函数返回当前配置选项的配置信息
加密函数进行加密、解密、数字签名和数字验证等操作
游标函数返回有关游标的信息
日期和时间函数执行与日期、时间数据相关的操作
数学函数执行数学运算,如三角函数等
元数据函数返回数据库和数据库对象的信息
排名函数返回分区中每一行的排名值
行集函数返回一个可用于代替Transact-SQL语句中表引用的对象
安全函数返回有关用户和角色的信息
字符串函数对字符串进行操作的函数,如子串函数
系统函数对系统各种选项和对象进行操作或报告
系统统计函数返回有关SQL server系统性能的统计信息
文本和图像函数执行更改TEXTIMAGE等操作

确定性函数和非确定性函数:

对于同一组输入,若输出一定,则该函数为确定性函数,如SQRT(float_expression);

对于同一组输入,若输出不确定,则该函数为非确定性函数,如GETDATE().

所有的配置函数、游标函数、元数据函数、安全函数以及系统统计函数等都是非确定性函数.

聚合函数

组合函数可以对一组值执行计算,并返回单个值.COUNT(args)外,其它聚合函数均可忽略NULL.

下面介绍几个常用的聚合函数:

COUNT(args)COUNT_BIG(args)函数:

用于统计组中找到的项数量,语法如下:

-- Aggregation Function Syntax 
COUNT ( { [ [ ALL | DISTINCT ] expression ] | * } )  

-- Analytic Function Syntax 
COUNT ( [ ALL ]  { expression | * } ) OVER ( [ <partition_by_clause> ] )

COUNT(args)COUNT_BIG(args)函数唯一的区别在于: 返回值不同,前者返回INT,后者返回BIGINT.

  • ALL选项: 对于组中所有值,都统计在内,这是COUNT(args)COUNT_BIG(args)的默认选项
  • DINSTINCT选项: 只统计唯一非NULL值的数量
  • expression: 任意类型(imagentexttext除外)的表达式.注意,不支持表达式中的聚合函数或子查询
  • *: 指定应对所有行计数,使用后不能指定其他参数,包括expression,因为此时无需指定任何列

下面是简单例子:

USE AdventureWorks2017;
GO

SELECT COUNT(*)  
FROM HumanResources.Employee;  
GO

AVG(args)函数:

返回组中各值的平均值,语法如下:

AVG ( [ ALL | DISTINCT ] expression )  
   [ OVER ( [ partition_by_clause ] order_by_clause ) ]
  • ALL: 向所有值应用此聚合函数.ALL为默认值.
  • DISTINCT: 指定AVG(args)只在每个值的唯一实例上执行,而不管该值出现了多少次.
  • expression: 精确数值或近似数值数据类型类别(BIT除外)的表达式.不允许使用聚合函数和子查询.
  • OVER ( [ partition_by_clause ] order_by_clause):
    partition_by_clause将FROM 子句生成的结果集划分为要应用函数的分区.如果未指定,则此函数将查询结果集的所有行视为单个组.order_by_clause确定执行操作的逻辑顺序.需要order_by_clause.

以下是COUNT(args)AVG(args)一同使用的示例:

USE AdventureWorks2017;
GO

SELECT COUNT(*), AVG(Bonus)  
FROM Sales.SalesPerson  
WHERE SalesQuota > 25000;  
GO  

以上程序的作用是: 统计Sales.SalesPerson表的数据项的总个数(销售人员的总数),求Bonus列平均值(符合条件: SalesQuota > 25000的数据项),并输出出来,运行结果如下:

《Transact-SQL语言》

说明: 14是表中数据项的名称,3472.1428是满足条件的Bouns列的平均值.

MAX(args)函数:

返回表达式中的最大值,语法如下:

-- Aggregation Function Syntax 
MAX( [ ALL | DISTINCT ] expression )  
  
-- Analytic Function Syntax 
MAX ([ ALL ] expression) OVER ( [ <partition_by_clause> ] [ <order_by_clause> ] )

以上参数在上面的聚合函数中已经提及,就不再进行说明,直接看一个例子:

USE AdventureWorks2017;
GO

SELECT MAX(TaxRate)  
FROM Sales.SalesTaxRate;  
GO

说明: 以上代码是从Sales.SalesTaxRate表中选出最高税率.

MIN(args)函数:

MAX(args)函数使用方法一模一样,只是功能是选择最小值而非最大值,直接看一个示例:

USE AdventureWorks2017;
GO

SELECT MIN(TaxRate)  
FROM Sales.SalesTaxRate;  
GO

说明: 以上代码是从Sales.SalesTaxRate表中选出最低税率.

SUM(args)函数:

返回表达式中所有值的和或仅非重复值的和.SUM(args)只能用于数字列.

-- Aggregate Function Syntax 
SUM ( [ ALL | DISTINCT ] expression )  

-- Analytic Function Syntax 
SUM ([ ALL ] expression) OVER ( [ partition_by_clause ] order_by_clause)  

可见SUM(args)的用法和其它聚合函数并无太大差异,示例如下:

SELECT Color, SUM(ListPrice), SUM(StandardCost)  
FROM Production.Product  
WHERE Color IS NOT NULL   
    AND ListPrice != 0.00   
    AND Name LIKE 'Mountain%'  
GROUP BY Color  
ORDER BY Color;  
GO

以上代码含义就不解释了,直接看结果吧:

《Transact-SQL语言》

配置函数

一下是SQL server提供的配置函数:

函数名描述
@@DBTS返回当前数据库最后使用的时间戳值.
@@LANGID返回当前使用的语言的本地语言标识符(ID).
@@LANGUAGE返回当前所用语言的名称.
@@LOCK_TIMEOUT返回当前会话的当前锁定超时设置(毫秒).
@@MAX_CONNECTIONS返回SQL Server实例允许同时进行的最大用户连接数.
@@MAX_PRECISION返回DECIMALNUMERIC数据类型所用的精度级别.
@@NESTLEVEL返回在本地服务器上执行的当前存储过程的嵌套级别(初始值为0).
@@OPTIONS返回有关当前SET选项的信息.
@@REMSERVER返回远程SQL Server数据库服务器在登录记录中显示的名称.
@@SERVERNAME返回正在运行SQL Server的本地服务器的名称.
@@SERVICENAME返回SQL Server正在其下运行的注册表项的名称.
@@SPID返回当前用户进程的会话ID.
@@TEXTSIZE返回TEXTSIZE选项的当前值.
@@VERSION返回SQL Server的当前安装的系统和生成信息.

关于配置函数的使用,其实非常简单,直接调用即可:

USE AdventureWorks2017;
GO  

SELECT @@DBTS;
SELECT @@VERSION AS 'SQL Server Version';
SELECT @@LOCK_TIMEOUT AS 'Lock Timeout';
SELECT @@LANGUAGE AS 'Language Name',@@LANGID AS 'Language ID';
GO

运行结果如下:

《Transact-SQL语言》

加密 && 游标函数

关于加密和游标函数,这里不作过多展开,感兴趣可以对照以下的内容去查阅官方文档:

对称加密和解密函数:
ENCRYPTBYKEYDECRYPTBYKEY
ENCRYPTBYPASSPHRASEDECRYPTBYPASSPHRASE
KEY_IDKEY_GUID
DECRYPTBYKEYAUTOASYMKEYKEY_NAME
SYMKEYPROPERTY
非对称加密和解密:
ENCRYPTBYASYMKEYDECRYPTBYASYMKEY
ENCRYPTBYCERTDECRYPTBYCERT
ASYMKEYPROPERTYASYMKEY_ID
签名和签名验证:
SIGNBYASYMKEYVERIFYSIGNEDBYASMKEY
SIGNBYCERTVERIGYSIGNEDBYCERT
IS_OBJECTSIGNED
含自动密钥处理的对称解密:加密哈希运算函数:
DecryptByKeyAutoCertHASHBYTES
证书复制函数:
CERTENCODED (Transact-SQL)CERTPRIVATEKEY (Transact-SQL)

以下标量函数可返回有关游标的信息:

所有游标函数都是非确定性的.

日期和时间函数

以下列出了一些常用的日期和时间函数:

函数语法返回值
DATEADDDATEADD(datepart,number,date)将一个时间间隔与指定date的指定datepart相加,返回一个新的datetime值
DATEDIFFDATEDIFF(datepart,startdate,enddate)返回两个指定日期之间所跨的日期或时间 datepart边界数
DATEDIFF_BIGDATEDIFF_BIG(datepart,startdate,enddate)返回两个指定日期之间所跨的日期或时间 datepart边界数
DATENAMEDATENAME(datepart,date)返回表示指定date的指定datepart的字符串
DATEPARTDATEPART(datepart,date)返回表示指定date的指定datepart的整数
GETDATEGETDATE()返回包含计算机的日期和时间的datetime 值,SQL Server的实例在该计算机上运行.返回值不包括时区偏移量
MONTHMONTH(date)返回表示指定date的“月”部分的整数
YEARYEAR(date)返回表示指定date的“年”部分的整数
DAYDAY(date)返回表示指定date的“日”部分的整数

在上面的语法中,datepart参数表示指定要返回新值的日期的组成部分,SQL server可用的日期部分及其缩写如下表所示,number表示要增加的新值.date指定原先的日期和时间数据.startdate和enddate分别指定开始日期和结束日期.

日期部分缩写
yearyy,yyyy
quarterqq,q
monthmm,m
dayofyeardy,y
daydd,d
weekwk,ww
weekdaydw,w
hourhh
minutemi,n
secondss,s
millisecondms

数学函数

这可能是我们最容易上手的函数了,因为其使用方式和日常数学形式并无二致,参数非常易于理解,以下是常用的数学函数集合:

  • ABS(numeric_expression): 绝对值函数,返回指定数值表达式的绝对值.
  • ACOS(float_expression): 反余弦函数,返回以弧度表示的角,定义域为[-1.00,1.00].
  • ASIN(float_expression): 反正弦函数,返回以弧度表示的角,定义域为[-1.00,1.00].
  • ATAN(float_expression): 反正切函数,返回以弧度表示的角.
  • ATN2(float_expression,float_expression): 返回以弧度表示的角,该角位于正X轴和原点至点(y,x)的射线之间,其中x和y是两个指定的浮点表达式的值.
  • CEILING(numeric_expression): 回大于或等于指定数值表达式的最小整数.
  • COS(float_expression): 返回指定表达式中以弧度测量的指定角的三角余弦值.
  • COT(float_expression): 返回指定表达式中以弧度测量的指定角的三角余切值.
  • RADIANS(numeric_expression): 对于在数值表达式中输入的度数值返回弧度值.
  • DEGREES(numeric_expression): 返回按弧度指定的角的相应角度数.
  • EXP(float_expression): 返回指定的float表达式的指数值.
  • FLOOR(numeric_expression): 返回小于或等于指定数值表达式的最大整数.
  • LOG(float_expression [,base]): 返回float表达式的自然对数,或以整型[base]为底的对数.
  • LOG10(float_expression): 返回float表达式的以10为底的对数.
  • POWER(float_expression,y): 返回指定表达式的指定幂的值.
  • PI(): 圆周率的常量值.
  • RAND([seed]): 返回一个 ∈ \in (0,1之间的伪随机float值,[seed]一般不指定.
  • ROUND(numeric_expression,length [,function]): 返回一个数值,舍入到指定的长度或精度.
  • SIGN(numeric_expression): 返回指定表达式的符号.
  • SIN(float_expression): 返回指定表达式中以弧度测量的指定角的三角正弦值.
  • SQRT(float_expression): 返回指定浮点值的平方根.
  • SQUARE(float_expression): 返回指定浮点值的平方.
  • TAN(float_expression): 返回指定表达式中以弧度测量的指定角的三角正切值.

其中,红色部分为常用数学函数.以下是一个演示:

SELECT SQRT($123.45), SQRT($100), SQRT($0.0);
SELECT SQUARE($123.45), SQUARE($-123.45), SQUARE($0.0);
SELECT CEILING($123.45), CEILING($-123.45), CEILING($0.0);
SELECT FLOOR(123.45), FLOOR(-123.45), FLOOR($123.45);
SELECT ABS(-1.0), ABS(0.0), ABS(1.0);
GO

运行结果如下:

《Transact-SQL语言》

排名函数

排名函数即排序函数,是用来对一些集合进行排序使用的,排名函数有以下几种:

函数名描述
RANK返回结果集分区中每一行的排名值,且存在并列排名(名次有间断).
DENSE_RANK返回结果集分区中每一行的排名值,且不存在并列排名(名次无间断).
NTILE将有序分区中的数据分发到指定数量的组中,每个组都有一个从1开始的编号.对每行数据,返回该行所属组的编号.
ROW_NUMBER返回结果集分区,内数据行的序列号.在每一个分区内,序列号都从1开始.

以下是这几个排名函数的使用示例:

USE AdventureWorks2017;  
GO  
SELECT p.FirstName, p.LastName  
    ,ROW_NUMBER() OVER (ORDER BY a.PostalCode) AS "Row Number"  
    ,RANK() OVER (ORDER BY a.PostalCode) AS Rank  
    ,DENSE_RANK() OVER (ORDER BY a.PostalCode) AS "Dense Rank"  
    ,NTILE(4) OVER (ORDER BY a.PostalCode) AS Quartile  
    ,s.SalesYTD  
    ,a.PostalCode  
FROM Sales.SalesPerson AS s   
    INNER JOIN Person.Person AS p   
        ON s.BusinessEntityID = p.BusinessEntityID  
    INNER JOIN Person.Address AS a   
        ON a.AddressID = p.BusinessEntityID  
WHERE TerritoryID IS NOT NULL AND SalesYTD <> 0;

运行结果如下:

《Transact-SQL语言》

安全函数

安全函数有很多,可以上这里看看.包括之前已经介绍过的IS_MEMBERIS_SRVROLEMEMBER.详细内容看文档.

字符串函数

字符串处理无论在什么语言中都很重要,因此字符串函数也很重要,介绍几个常用的:

函数名描述
LEFT(character_expression,integer_expression)返回字符串中从左边开始指定个数的字符
RIGHT(character_expression,integer_expression)返回字符串中从右边开始指定个数的字符
LEN(string_expression)返回字符串的长度,不统计尾随空格
LOWER(character_expression)返回字符数据转换为大写的字符表达式
UPPER(character_expression)返回字符数据转换为大写的字符表达式
TRIM([characters FROM] string)返回删除两头空格字符或指定字符的字符串
LTRIM(character_expression)返回删除了前导空格之后的字符表达式
RTRIM(character_expression)返回删除了后导空格之后的字符表达式
REPLACE(string_expression,pattern,string_replacement)用另一个字符串替换出现的所有模式串
REPLICATE(string_expression,integer_expression)以指定的次数重复字符串
REVERSE(string_expression)返回字符串值的逆序
SUBSTRING(expression,start,length)返回字符、二进制、文本或图像的一部分

以下是一个示例:

SELECT
	TRIM( '.,! ' FROM  '!# test .'),
	SUBSTRING('Hello World',7,5),
	LTRIM(' Hello World '),
	RTRIM(' Hello World '),
	TRIM(' Hello World '),
	UPPER('Hello World'),
	LOWER('Hello World'),
	REPLACE('Hello World','World','Code'),
	REPLICATE('Hello World',2),
	REVERSE('Hello World'),
	LEN('Hello World'),
	LEFT('Hello World',5),
	RIGHT('Hello World',5);
GO

运行结果如下:

《Transact-SQL语言》

注意: SQL server的字符串位置从1开始,而非其它语言(如C)是从0开始的.

系统函数

关于系统函数,想了解的话可以看这里.学会使用即可,下面介绍几个常用的系统函数:

  • CASE: 计算条件列表,并返回多个可能的结果表达式之一.
  • CASTCONVERT将表达式由一种数据类型转换为另一种数据类型.
  • IDENTITY(data_type [,seed,increment]) AS column_name: 使用SELECT INTO将标识符插入到新表中.
  • ISDATE(expression): 如果表达式是有效的DATETIME、或DATETIME值,则返回1;否则返回0.
  • ISNULL(check_expression,replacement_value): 使用指定的替换值替换NULL.
  • ISNUMERIC(expression): 确定表达式是否为有效的数值类型.
  • NULLIF(expression1,expression2): 如果两个指定的表达式相等,则返回空值.
  • @@ROWCOUNT: 返回受上一语句影响的行数.如果行数大于20亿,请使用ROWCOUNT_BIG.

此外还有如@@ERRORERROR_LINEERROR_MESSAGEERROR_NUMBERERROR_PROCEDUREERROR_SEVERITYERROR_STATE等系统错误函数,之前说过了,就不再提.

以上就是Transact-SQL语言的粗略内容,下篇我们会讲到表的具体操作.

上一篇: 管理数据库
下一篇:

    原文作者:AAMahone
    原文地址: https://blog.csdn.net/AAMahone/article/details/88662171
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞