目录
[1.1 标识符](#1.1 标识符)
[1. 常规标识符](#1. 常规标识符)
[2. 分隔标识符](#2. 分隔标识符)
[1.2 变量](#1.2 变量)
[1. 全局变量](#1. 全局变量)
[2. 局部变量](#2. 局部变量)
[1.3 运算符](#1.3 运算符)
[1. 算数运算符](#1. 算数运算符)
[2. 赋值运算符](#2. 赋值运算符)
[3. 位运算符](#3. 位运算符)
[4. 比较运算符](#4. 比较运算符)
[5. 逻辑运算符](#5. 逻辑运算符)
[6. 字符串连接运算符](#6. 字符串连接运算符)
[7. 一元运算符](#7. 一元运算符)
[8. 运算符的优先级和结合性](#8. 运算符的优先级和结合性)
[1.4 批处理](#1.4 批处理)
[1.5 注释](#1.5 注释)
[2.1 BEGIN...AND](#2.1 BEGIN…AND)
[2.2 IF...ELSE](#2.2 IF…ELSE)
[2.3 CASE](#2.3 CASE)
[2.4 WHILE...CONTINUE...BREAK](#2.4 WHILE…CONTINUE…BREAK)
[2.5 RETURN](#2.5 RETURN)
[2.6 RAISERROR](#2.6 RAISERROR)
[3.1 系统内置函数](#3.1 系统内置函数)
[3.2 用户自定义函数](#3.2 用户自定义函数)
[1. 标量值函数](#1. 标量值函数)
[2. 内联表值函数](#2. 内联表值函数)
[3. 多语句表值函数](#3. 多语句表值函数)
[4.1 游标的概述](#4.1 游标的概述)
[4.2 游标的类型](#4.2 游标的类型)
[1. 只进游标](#1. 只进游标)
[2. 静态游标](#2. 静态游标)
[3. 键集游标](#3. 键集游标)
[4. 动态游标](#4. 动态游标)
[4.3 游标的使用](#4.3 游标的使用)
[1. 声明游标](#1. 声明游标)
[2. 打开游标](#2. 打开游标)
[3. 提取数据](#3. 提取数据)
[4. 关闭游标](#4. 关闭游标)
[5. 释放游标](#5. 释放游标)
[4.4 定位修改游标](#4.4 定位修改游标)
[4.5 定位删除游标](#4.5 定位删除游标)
T-SQL的语法约定
1、T-SQL的元素
1.1 标识符
1. 常规标识符
-
必须以汉字 、字母 、下划线_ 、@ 、#开头 ,后续字符可以是数字 、汉字 、字母 、下划线_ 、@ 、# 的组合。
-
不能是 SQL Server 的关键字。
-
不能超过128个字符。
2. 分隔标识符
需要使用分隔标识符的情况:放在方括号 [ ]或双引号 **" "**中
-
标识符的命名不符合常规标识符格式的规则。
-
使用关键字 作为对象名 或对象名的一部分。
1.2 变量
1. 全局变量
由系统提供 且预先声明 ,全局变量名由"@@"符号开始。
用户只能使用 全局变量,不能 进行修改。
作用域 是整个SQL Server 系统,任何程序都可以随时调用它们。
2. 局部变量
一般在批处理(go),过程(procedure)中可见。
定义(DECLARE):局部变量名由"@"符号开始。一定要先定义再使用。
sql
DECLARE {@local_variable data_type}[,...n]
赋值(SET|SELECT):
sql
-- 只能对单个变量赋值
SET {@local_variable = expression}
--可对多个变量赋值
SELECT {@local_variable = expression}[,...n]
输出(PRINT|SELECT):
sql
-- 只能单个字符串|局部变量|字符串表达式
PRINT {msg_str|@local_variable|string_expr}
-- 可以多个局部变量的值
SELECT {@local_variable}[,...n]
局部变量的作用域:批处理(go),过程(procedure)中。
例:
sql
DECLARE @myvar char(20),@i int
SET @myvar = 'This is a test'
SET @i=20
SELECT @myvar as a ,@i as b
GO
1.3 运算符
1. 算数运算符
加(+),减(-),乘(*),除(/),取模(%)。
注意:取模(%),只能是****int,tinyint,smallint。
2. 赋值运算符
T-SQL中只有一个赋值运算符,即等号(=)。
3. 位运算符
按位与(&),按位或(|),按位异或(^)。
注意:两个数据可以是整型数据 或二进制数据 ,但不能同时是二进制数据。
4. 比较运算符
=、>、<、>=、<=、<>(!=)。
运算结果为逻辑值:TRUE,FALSE,UNKNOWN(当NULL参与时)。
5. 逻辑运算符
返回值为TRUE或FALSE或UNKNOWN(当NULL参与时)。
ALL:如果一组的比较都为TRUE,那么就为,TRUE。
AND:如果两个布尔表达式都为TRUE,那么就,为 TRUE。
ANY:如果一组的比较中任何一个为TRUE,那,么就为TRUE。
BETWEEN:如果操作数在某个范围之内,那么就为,TRUE。
EXISTS:如果子查询包含一些行,那么就为TRUE。
IN:如果操作数等于表达式列表中的一个,那么就为TRUE。
LIKE:如果操作数与一种模式相匹配,那么就为,TRUE。
NOT:对任何其他布尔运算符的值取反。
OR:如果两个布尔表达式中的一个为TRUE,那么就为TRUE。
SOME:如果在一组比较中,有些为TRUE,那么就为TRUE。
6. 字符串连接运算符
"+"
7. 一元运算符
"+",正,"-",负,"~",按位取反(只能是整数数据类型)。
8. 运算符的优先级和结合性
级别 | 运算符 |
---|---|
1 | ~(按位取反) |
2 | *(乘)、/(除)、%(取模) |
3 | +(正)、-(负)、+(加)、+(串联)、-(减)、&(位与)、^(位异或)、|(位或) |
4 | =、>、<、>=、<=、<>(!=)、!>、!< |
5 | NOT |
6 | AND |
7 | ALL、ANY、BETWEEN、IN、LIKE、OR、SOME |
8 | =(赋值) |
1.4 批处理
批处理 是包含一个或多个T-SQL语句 的集合 ,从应用程序一次性地发送到SQL Server2014进行执行,一次可以节省系统开销。SQL Server将批处理的语句编译为一个可执行单元,称之为执行计划,批处理的结束符为"GO"。
编译错误 (如:语法错误)可使执行计划无法编译。因此未执行批处理中的任何语句。
运行时错误(如:算术溢出或违反约束)会产生以下两种影响之一:
-
大多数 运行时错误,将停止执行 批处理中,当前语句及后面的语句。
-
某些运行时错误(如:违反约束 )仅停止执行当前语句 ,而继续执行 批处理中的其他语句。
1.5 注释
"--" 或 "/*......*/"
2、流程控制语句
2.1 BEGIN...AND
sql
BEGIN
{sql_statement|statement_block}
END
sql_statement|statement_block:T-SQL语句|语句块。
BEGIN...END主要用于下列情况:
WHILE,CASE,IF...ELSE。
BEGIN...END可以嵌套。
2.2 IF...ELSE
sql
IF Boolean_expression
{sql_statement|statement_block}
[ELSE {sql_statement|statement_block}]
IF...ELSE语句可以嵌套。
如果Boolean_expression中有SELECT语句,要加**()**。
例:如果,学号"20160211"的学生选修的,课程号为"0101"的课程成绩>=90,"成绩优秀",否则"成绩一般"。
sql
USE teaching
GO
IF ( SELECT score FROM sc WHERE sno='20160211' and cno='0101') >=90
PRINT '成绩优秀'
ELSE
PRINT '成绩一般'
2.3 CASE
简单CASE格式:(CASE后面)某个表达式与(WHEN后面)一组简单表达式或常量进行比较,以确定结果。
搜索CASE格式:计算(WHEN后面)一组布尔表达式,以确定结果。
例:查询所有学生的考试等级,包括学号,课程号,成绩等级(优秀,良好,中等,及格,不及格)
简单CASE: 整数/整数 = 整数
sql
use teaching
select sno as 学号,cno as 课程号,
CASE score/10
when 10 then '优秀'
when 9 then '优秀'
when 8 then '良好'
when 7 then '中等'
when 6 then '及格'
else '不及格'
END
from sc
搜索CASE(推荐):
sql
use teaching
select 学号=sno,课程号=cno,成绩等级=
CASE
when score>=90 then '优秀'
when score>=80 then '良好'
when score>=70 then '中等'
when score>=60 then '及格'
else '不及格'
END
from sc
2.4 WHILE...CONTINUE...BREAK
sql
WHILE Boolean_expressionession
[BEGIN]
sql_statement|statement_block [BREAK|CONTINUE]
[END]
例:求1到100的累加,并输出。
sql
DECLARE @i int,@sum int
SELECT @i = 1,@sum = 0
WHILE @i <= 100
BEGIN
SET @sum = @sum+@i
SET @i = @i+1
END
SELECT @sum as 'sum',@i as 'i'
2.5 RETURN
可以从查询或过程中无条件退出。
2.6 RAISERROR
RAISERROR:将错误信息显示在屏幕上,同时也可以记录在NT日志中。
sql
RAISERROR{{msg_id|msg_str},severity,state}
msg_id|msg_str:错误信息。
severity:错误的严重级别。
state:发生错误时的状态信息。
如:
sql
RAISERROR('NO !',16,1)
3、函数
3.1 系统内置函数
聚合函数,数学函数,日期和时间函数,字符串函数。
强制类型转换函数:
CAST( expression AS data_type[(length)] )
如:把int类型的@age强制转换为char(2)类型
sql
CAST(@age as char(2))
CONVERT(data_type[(length),expression[,style])
3.2 用户自定义函数
1. 标量值函数
一般需要declare变量。
sql
CREATE FUNCTION [schema_name.]function_name
([{@parameter_name parameter_data_type [= default_expression]}[,...n]])
RETURNS return_data_type
[AS] -- 一般不省略
BEGIN
function_body
RETURN expression
END
GO
注意:调用标量值函数,需要指定架构名,默认 为dbo。
例:创建一个标量值函数,接受学号,返回该学号的平均成绩。
sql
use teaching
go
create function avgscore(@sno char(8))
returns tinyint
as
begin
declare @avgscore tinyint
select @avgscore=avg(score)
from sc
where sno = @sno
return @avgscore
end
go
-- 调用标量值函数,需要指定架构名,默认为dbo
select dbo.avgscore('20160211') as '平均成绩'
2. 内联表值函数
一般不需要declare变量。
sql
CREATE FUNCTION [schema_name.]function_name
([{@parameter_name parameter_data_type [= default_expression]}[,...n]])
RETURNS TABLE
[AS] -- 一般不省略
RETURN(select_statement)
注意:内联表值函数返回的是表。
例1:创建一个内联表值函数,查询各个专业的专业名称及学生人数的。
sql
use teaching
go
create function ZY_RS() -- ()不能省略
returns table
as
return(
select specialty,count(*) as '学生人数'
from student
group by specialty)
go
select * from ZY_RS() -- 返回的是一个表,所以from
例2:创建一个内联表值函数,接受课程号,返回该课程号的选修信息,不传课程号,就返回所有课程号的选修信息。
sql
use teaching
go
create function XK
(@cno varchar(4) = '%') -- 如果是char(4),实际上是'%'+3个空格
returns table
as
return(
select * from sc where cno like @cno)
go
select * from XK('0101') -- 特定课程号的选修信息
select * from XK(default) -- 全部选修信息
3. 多语句表值函数
可以自定义返回表 的结构。
sql
CREATE FUNCTION [schema_name.]function_name
([{@parameter_name parameter_data_type [= default_expression]}[,...n]])
RETURNS @return_variable TABLE<table_definition>
[AS] -- 一般不省略
BEGIN
function_body
RETURN
END
例:创建一个多语句表值函数,查询选修特定课程名的学号,姓名,课程号,课程名,成绩
sql
use teaching
go
create function KCM_XK(@cname varchar(32))
-- 返回的表名必须是局部变量名的形式(@)
returns @xk table(学号 char(8),姓名 varchar(10),
课程号 char(4),课程名 varchar(32),成绩 tinyint)
as
begin
insert into @xk
select s.sno,s.sname,sc.cno,c.cname,sc.score -- 对应好表中的列
from sc inner join student as s on sc.sno = s.sno -- 不需要逗号
inner join course as c on sc.cno = c.cno
where c.cname = @cname
return
end
go
select * from KCM_XK('C语言')
4、游标
4.1 游标的概述
游标 是处理数据的一种方式,它允许应用程序每一次处理一行或一部分行。
游标可以看作一个指针 ,可以指定结果中的任何位置。
4.2 游标的类型
1. 只进游标
FORWARD_ONLY,即只进游标只能 从第一行滚动到最后一行。
2. 静态游标
STATIC,静态游标 在打开时 会创建 一个数据快照 ,该快照不会随着后续数据库的修改而改变。
静态游标是在数据快照上进行操作。
3. 键集游标
KEYSET,键集游标 在打开时,会固定结果集 中行 的成员身份和顺序 。这意味着,当游标打开后,即使底层数据表中的数据发生变化,游标所指向的行集也不会改变(除非这些行的键被更改)。然而,与静态游标不同的是,如果结果集中的行由于键的更改而被删除或更新 ,这些更改在键集游标中 是可见的。
4. 动态游标
DYNAMIC,动态游标 与静态游标相对,反映结果集中所做的所有更改。
4.3 游标的使用
1. 声明游标
sql
DECLARE cursor_name CURSOR
[LOCAL | GLOBAL] -- 局部|全局
[FORWARD_ONLY | SCROLL] -- 只进|滚动
[STATIC | KEYSET | DYNAMIC | FAST_FORWARD]
[READ_ONLY | SCROLL_LOCKS | OPTIMISTIC]
FOR select_statement
[FOR UPDATE [OF column_name [,...n]]] -- 通过游标进行修改
2. 打开游标
sql
OPEN {{[GLOBAL] cursor_name}|cursor_variable_name}
3. 提取数据
sql
-- 下一行|上一行|第一行|最后一行
FETCH [[NEXT|PRIOR|FIRST|LAST|
ABSOLUTE {n|@nvar}|RELATIVE {n|@nvar}]FROM] -- 指定第几行|相对当前行的第几行
{{[GLOBAL] cursor_name}|cursor_variable_name}
[INTO @variable_name [,...n]] -- 提取到变量中
4. 关闭游标
sql
CLOSE {{[GLOBAL] cursor_name}|cursor_variable_name}
5. 释放游标
sql
DEALLOCATE {{[GLOBAL] cursor_name}|cursor_variable_name}
4.4 定位修改游标
例:声明一个游标,用以更新第五个女生的年龄信息。
sql
USE teaching
DECLARE S_Cur1 SCROLL CURSOR
FOR
SELECT * FROM student WHERE ssex='女'
FOR UPDATE
GO
OPEN S_Cur1
GO
FETCH ABSOLUTE 5 FROM S_Cur1
GO
UPDATE student SET Sage=20
WHERE CURRENT OF S_Cur1 -- CURRENT OF,修改当前游标所指定的行
GO
CLOSE S_Cur1
GO
DEALLOCATE S_Cur1
注意:
(1)定位修改一次只能更新 当前游标位置确定的一行。OPEN语句将游标位置定位在结果集第一行前 ,可以使用FETCH语句把游标位置定位在要被更新的数据行处。
(2)进行定位修改所使用的游标必须声明为FOR UPDATE 方式。进行定位修改 数据表中的行时 ,不移动游标位置。被更新的行可以再次被修改,直到下一个FETCH语句的执行。
(3)定位修改 可以更新多数据表或被连接的多表,但只能更新其中一个表的行,即所有被更新的列都来自同一个表。
4.5 定位删除游标
例:声明一个游标,用以删除最后一个女生记录。
sql
USE teaching
DECLARE S_Cur2 SCROLL CURSOR
FOR
SELECT * FROM student WHERE ssex='女'
FOR UPDATE
GO
OPEN S_Cur2
GO
FETCH LAST FROM S_Cur2
GO
DELETE student
WHERE CURRENT OF S_Cur2 -- CURRENT OF,删除当前游标所指定的行
GO
CLOSE S_Cur2
GO
DEALLOCATE S_Cur2
注意:
(1)进行定位删除 时,一次只能删除当前游标位置确定的一行,删除后游标位置向前移动一行。OPEN语句将游标位置定位在结果集第一行前 ,可以使用FETCH语句把游标位置定位在要被删除的行处。
(2)进行定位删除所使用的游标必须声明为FOR UPDATE 方式。而且声明游标的SELECT语句不能含有连接操作或涉及多表。否则,即使声明中指明了FOR UPDATE 方式,也不能删除其中的行。
(3)对使用游标删除行的数据表 ,要求有一个唯一索引。