创建表三种方式:
1、创建临时表:create table #temp(column_1 varchar(16),column_2 varchar(16))
2、创建实体表:create table table_name()
3、复制实体表:select * into newTableName from oldTableName
对虚表进行备份:select * into newTableName from #temp
/*
创建学生表、教师表、课程表、成绩表
学生表:学号(主键)、姓名、性别、生日、专业、总学分
教师表:教师编号(主键),姓名,性别,出生日期,教授学科,学校
课程表:编号(主键),课程名称,学分,教师编号
分数:学号,课程号,分数
*/
--创建学生表
if exists(select * from sysobjects where id=OBJECT_ID(N'dbo.student'))
begin
drop table student
end
create table student(
stno varchar(16) not null primary key,
stname varchar(16) not null,
stsex varchar(16) not null,
stbirthday date not null,
speciality varchar(16) null,
tc int null
)
--创建教师表
if exists (select * from sysobjects where id=OBJECT_ID(N'teacher'))
begin
drop table teacher
end
create table teacher(
tno varchar(16) not null primary key,
tname varchar(16) not null,
tsex varchar(16) not null,
tbirthday date not null,
title varchar(16) null,
school varchar(16) null
)
--创建课程表
if exists (select * from sysobjects where id=object_id(N'course'))
begin
drop table course
end
create table course(
cno varchar(16) not null primary key,
cname varchar(16) not null,
credit int not null,
tno varchar(16) not null
)
--创建分数表
if exists (select * from sysobjects where id=OBJECT_ID(N'score'))
begin
drop table score
end
create table score(
stno varchar(16) not null,
cno varchar(16) not null,
score float null,
primary key (stno,cno)
)
--创建客户表
if exists (select * from sysobject where id = object_id(N'client'))
begin
drop table client
end
create table client(
id varchar(16) not null primary key,
name varchar(16) not null,
gender varchar(16) not null,
adress varchar(20) null
)
alter table 表名
add 列名 数据类型 约束条件
--1、在学生表中增加remark列
alter table student
add remark varchar(16) not null
exec sp_rename ‘表名.列名’,‘新列名’,‘column’
--2、将remark列名称改为grade
exec sp_rename 'student.remark','grade','column'
alter table 表名
alter column 列名 数据类型 约束条件
--3、将grade列属性,数据类型设置为char(10),可以为空值
alter table student
alter column grade char(10) null
alter table 表名
drop column 列名
alter table student
drop column grade
drop table 表名
--删除客户表
drop table client
insert into 表名 values 数据 --列名必须指定
指定列插入
insert into 表名 values 数据
select 列名
into 新表名
from 旧表名
insert into 表名(列名)
select 列名
from 表名
--1、在学生表、课程表、成绩表、教师表中插入数据
insert into student values
('121002','周殷雪','女','1993-01-12','通信',49),
('121001','李贤友','男','1991-12-30','通信',52),
('121005','刘刚','男','1992-07-05','通信',50),
('122001','郭德强','男','1991-10-23','计算机',48),
('122002','谢萱','女','1992-09-11','计算机',52),
('122004','孙婷','女','1991-02-24','计算机',50),
('122006','张三','男','1992-07-23','计算机',53)
insert into course values
('102','数字电路',3,'102101'),
('203','数据库系统',3,'204101'),
('205','微机原理',4,'204107'),
('208','计算机网络',4,null),
('801','高等数学',4,'801102')
insert into score values
('121001','102',92),
('121002','102',72),
('121005','102',87),
('122002','203',94),
('122004','203',81),
('121001','205',91),
('121002','205',65),
('121005','205',85),
('121001','801',94),
('121002','801',73),
('121005','801',82),
('122001','801',null),
('122002','801',95),
('122004','801',86)
insert into teacher values
('102105','周学莉','女','1977-10-05','讲师','通信学院'),
('204101','吴波','男','1978-04-26','教授','计算机学院'),
('204107','王冬琴','女','1968-11-18','副教授','计算机学院'),
('801102','李伟','男','1975-08-19','副教授','计算机学院')
update 表名
(修改)set
(条件限制)where
--2、将student表中张三的名字改为李四
update student
set stname = '李四'
where stno = '122006'
# 两个表级联进行更新
update score
set score.grade=score.grade+1
from score left join student
on score.stno=student.stno
where student.stno='121001' and score.cno='102'
DELETE TABLE 表名 WHERE 条件
TRUNCATE TABLE 表名
SQL中的Delete语句从表中删除一条或多条记录,同时可以给Delete语句提供Where子句,SQL中的 Select语句中可以使用的任何条件都可以在DELETE的WHERE子句中使用。
TRUNCATE TABLE 删除表中的所有行,但表结构及其列、约束、索引等保持不变。若要删除表定义及其数据,请使用 DROP TABLE 语句。如果表包含标识列,该列的计数器重置为该列定义的种子值。如果未定义种子,则使用默认值 1。若要保留标识计数器,请使用 DELETE。TRUNCATE TABLE 不能激活触发器,因为该操作不记录各个行删除。
--3、删除张三记录
delete student --删除表,可以加限制条件
where stno = '122006'
truncate table 表名 --删除数据,不能加限制条件,删除没有事务日志
--投影查询
--4、查询student表中的所有列
select *
from student
--5、查询student表中通信专业学生的stno、stname、tc,并将结果中各列的标题分别修改为学号、姓名、总学分
select stno 学号,stname 姓名,tc 总学分
from student
--6、查询student表中的speciality列,消除结果中的重复行
select distinct speciality 专业
from student
比较 <=,<,=,>=,>,<>
指定范围 between and, not between and, in
确定集合 in,not in
字符匹配 like,not like
%:代表0或者多个字符
_:代表一个字符
空值 is null,is not null null值进行条件匹配
多重条件 and,or
--选择查询
--7、查询student表中专业为计算机或者性别为女的学生
select *
from student
where speciality='计算机' or stsex='女'
--8、查询score表中成绩为82、91、95的记录
select *
from score
where grade in (82,91,95)
--9、查询student表中姓孙的学生情况
select *
from student
where stname like '孙%'
--10、查询已选课但未参加考试的学生情况
select *
from student
where stno in
(select stno
from score
where grade is null)
(1)连接谓词表现形式:<=,<,=,>=,>,!=,<>,!>,!<,between and, not between and
(2)使用join表现形式:left join,right join,inner join,cross join,cross apply,out join
left join替换为 in,exists
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-9RklK011-1629360943816)(C:\Users\Administrator\AppData\Roaming\Typora\typora-user-images\image-20210811140540587.png)]
--连接查询
--11、查询学生的情况和选修课程的情况
select a.stno 学号,a.stname 姓名,b.cname 课程
from student a, course b,score c
where a.stno=c.stno and b.cno=c.cno
--12、查询选修了微机原理且成绩在80分以上的学生姓名
select a.stname 姓名
from student a, course b,score c
where a.stno=c.stno and b.cno=c.cno and b.cname='微机原理' and grade > 80
--13、查询选修了801课程的成绩高于学号为121002的成绩的学生姓名
select stname 姓名
from student
where stno in(
select stno from score where cno='801' and grade>
(select grade from score where cno='801' and stno='121002'))
--14、查询选修了102课程且成绩在85分以上的学生情况
select a.stname 姓名,b.cname 课程,c.grade 成绩
from student a, course b,score c
where a.stno=c.stno and b.cno=c.cno and b.cno='102' and grade>85
--15、(内连接)查询学生的情况和选修课程的情况
select a.stname,b.cno
from student a inner join score b on a.stno = b.stno
--16、(内连接)查询选修了102课程且成绩在85分以上的学生情况
select *
from student a inner join score b on a.stno=b.stno
where cno='102' and grade>85
--17、(左外连接)采用左外连接查询教师的任课情况
select a.tname 教师姓名,b.cname 教授课程
from teacher a left join course b on a.tno = b.tno
--18、(右外连接)采用右外连接查询教师的任课情况
select a.tname 教师姓名,b.cname 教授课程
from teacher a right join course b on a.tno = b.tno
--19、(全外连接)采用全外连接查询教师的任课情况
select a.tname 教师姓名,b.cname 教授课程
from teacher a full join course b on a.tno = b.tno
--20、(交叉连接)查询教师和课程所有的组合情况
select a.tname,b.cname
from teacher a cross join course b
(1)聚合函数
AVG 求组中数值的平均值
COUNT 求组中的项数
MAX 求最大值
MIN 求最小值
SUM 返回表达式数值的总和
(2)group by
(3)HAVING子句:用于对分组按指定条件进行进一步筛选,最后只输出满足指定条件的分组
执行顺序:
执行where子句,在表中选择行
执行GROUP BY子句,对选取行进行分组
执行聚合函数
执行HAVING子句,筛选满足条件的分组
(4)ORDER BY:ASC 升序,DESC 降序
--统计计算
--21、查询102课程的最高分、最低分、平均分
select max(grade) 最高分,min(grade) 最低分,AVG(grade) 平均分
from score
where cno='102'
--22、求学生的总人数
select COUNT(*) 学生总人数
from student
--23、查询计算机专业学生的总人数
select count(*) 计算机专业总人数
from student
where speciality = '计算机'
--group by
--24、查询各门课程的最高分、最低分、平均成绩
select b.cname 课程名,min(grade) 最低分,max(grade) 最高分,AVG(grade) 平均成绩
from score a,course b
where a.cno=b.cno
group by b.cname
--25、求选修各门课程的平均成绩和选修人数
select b.cname 课程名,avg(a.grade) 平均成绩,count(*) 选修人数
from score a,course b
where a.cno=b.cno
group by b.cname
--HAVING
--26、查询选修课程两门以上且成绩在80分以上的学生的学号
select stno 学号,count(*) 选修课程数
from score
where grade>80
group by stno
having count(*)>1
--27、查询至少有4名学生选修且以8开头的课程号和平均分数
select cno 课程号,AVG(grade) 平均分数
from score
where cno like '8%'
group by cno
having count(*) >= 4
--ORDER BY
--28、将计算机专业的学生按出生时间先后顺序
select *
from student
where speciality='计算机'
order by stbirthday
--29、将通信专业学生按“数字电路”课程成绩降序排序
select a.stname,b.cname,c.grade
from student a, course b, score c
where a.stno=c.stno and b.cno=c.cno and b.cname='数字电路' and a.speciality='通信'
order by c.grade desc
(1)in 子查询:用于进行一个给定值是否在子查询结果集中的判断(尽量不用,在数据量大的时候不用)
(2)比较子查询
(3)EXISTS子查询:若返回不为空表,返回TRUE;NOT EXISTS若返回空表,返回TRUE(尽量不用)
--子查询
--30、查询选修了课程号为203的课程的学生情况
select *
from student
where stno in(
select stno
from score
where cno = '203'
)
--31、查询选修某课程的学生人数多于4人的教师姓名
select b.tname 教师姓名
from course a, teacher b
where a.tno=b.tno and cno in(
select cno
from score
group by cno
having count(*) > 4)
--比较子查询
--32、查询比所有计算机专业学生年龄都小的学生
select *
from student
where speciality = '通信' and stbirthday >
(select max(stbirthday)
from student
where speciality = '计算机')
--33、查询课程号801的成绩高于课程号205成绩的学生
select *
from student
where stno in (
select a.stno
from (select * from score where cno = '801') a,
(select * from score where cno = '205') b
where a.stno = b.stno and a.grade>b.grade)
--书本答案:
select stno
from score
where cno= '801' and grade >= any
( select grade
from score
where cno = '205'
)
--EXISTS子查询
--34、查询选修205课程的学生姓名
select *
from student
where exists(
select *
from score
where student.stno = score.stno and cno = '205')
--35、查询所有认课教师姓名和所在学院
select tname 姓名,school 所在学院
from teacher
where exists(
select *
from course
where course.tno=teacher.tno
)
(1)UNION:将多个结果合并成一个结果集,要求一是要求所有的列数和列的顺序必须相同,二是
数据类型必须相同
union和union all的区别是,union会自动压缩多个结果集合中的重复结果,而union all则将所有的结果全部显示出来,不管是不是重复。
Union:对两个结果集进行并集操作,不包括重复行,同时进行默认规则的排序;
UNION在进行表链接后会筛选掉重复的记录,所以在表链接后会对所产生的结果集进行排序运算,删除重复的记录再返回结果。
实际大部分应用中是不会产生重复的记录,最常见的是过程表与历史表UNION
Union All:对两个结果集进行并集操作,包括重复行,不进行排序;
如果返回的两个结果集中有重复的数据,那么返回的结果集就会包含重复的数据了。
(2)EXCEPT和INTERSECT:用于比较两个查询结果,返回非重复值,EXCEPT从左查询中返回右查询
没有找到的所有非重复值,INTERSECT返回INTERSECT操作数左、右两边的两个查询都返回的所有
非重复值。基本规则:所有查询中的列数和列的顺序必须相同,数据类型必须相同。
(3)INTO子句:用于创建新表并将查询所得的结果插入新表中
(4)临时表CTE:with 临时表名(字段) as 查询
(5)TOP谓词:在使用select语句进行查询时,有时需要列出前几行数据,可以使用TOP谓词对
结果集进行限定
TOP n :取前n行
TOP n percent:取前百分比
--UNION连接
--36、查询总学分大于50及学号小于121051的学生
select *
from student
where tc > 50
union all
select *
from student
where stno < '121051'
--EXCEPT和INTERSECT查询
--37、查询学过801课程但未学过102课程的学生
select a.stname
from student a,course b,score c
where a.stno = c.stno and b.cno = c.cno and b.cno='801'
except
select a.stname
from student a,course b,score c
where a.stno = c.stno and b.cno = c.cno and b.cno='102'
--38、查询既学过801课程又学过102课程的学生
select a.stname
from student a,course b,score c
where a.stno = c.stno and b.cno = c.cno and b.cno='801'
intersect
select a.stname
from student a,course b,score c
where a.stno = c.stno and b.cno = c.cno and b.cno='102'
--INTO子句
--39、由student表创建st表,包括学号、姓名、性别、专业和学分
select stno,stname,stsex,speciality
into st
from student
drop table st
--临时表
--40、使用临时表从score表中查询学号、课程号和成绩,并指定新列名为c_stno、c_cno、c_grade,再使用
--select语句从临时表和student表中查询姓名为“孙婷”的学生的学号、课程号和成绩
with temp_st(c_stno,c_cno,c_grade)
as (select stno,cno,grade from score)
select c_stno,c_cno,c_grade
from student a,temp_st b
where a.stno=b.c_stno and a.stname = '孙婷'
--41、计算1~10的阶乘
with Cfact(n,k)
as (
select n=1,k=1
union all
select n=n+1,k=k*(n+1)
from Cfact
where n<10
)
select n, k from Cfact
# 取连续数
with num
as(
select 1 number
union all
select number=number+1
from num
where number < 10000000)
select * from num
OPTION (maxrecursion 0)
# 取连续日期
DECLARE @DATE_BEGIN DATETIME = N'2021-01-01';
DECLARE @DATE_END DATETIME = N'2021-12-31';
WITH TEMP AS
(
SELECT @DATE_BEGIN N
UNION ALL
SELECT N+1
FROM TEMP
WHERE N+1<= @DATE_END
)
SELECT * FROM TEMP
OPTION(MAXRECURSION 0)
--42、查询总学分再前两名的学生
select top 2 stno,stname,tc
from student
order by tc desc
--43、查询总学分在前三名的学生情况
select top 3 with TIES stno,stname,speciality,tc
from student
order by tc desc
CREATE VIEW view_name
AS select_statement
[WITH CHECK OPTION]
--1、使用CREATE VIEW语句在stsc数据库中创建st2_comm视图,包括学号、姓名、课程号、成绩,且专业为通信
create view st_comm(stno,stname,cno,grade)
as
select a.stno 学号,a.stname 姓名,b.cno 课程号,b.grade 成绩
from student a, score b
where speciality = '通信' and a.stno = b.stno
--查询视图
--2、查询st_comm
select *
from st_comm
--3、查询通信专业学生的学号、姓名、课程名。
select stno ,stname,cno
from st_comm
--4、查询平均成绩在85分以上的学生的学号和平均成绩。
create view sc_avg(stno,avg_grade)
as
select a.stno,avg(grade)
from student a,score b
where a.stno=b.stno
group by a.stno
having avg(grade) > 85
更新视图指通过视图进行插入、删除、修改数据,由于视图是不存在数据的虚表,对视图的更新最终
转换为对基表的更新
通过更新视图数据可更新基表数据,但只有满足可更新条件的视图才能更新,可更新视图必须满足的条件是创建
视图的select语句没有聚合函数,且没有TOP、GROUP BY、UNION子句及DISTINCT关键字,不包含从基表列通过计算所
得的列,且FROM子句至少包含一个基本表
--插入数据
--6、向st_cp视图中插入记录('122009','董智强','男','1992-11-23','计算机',50)
insert into st_cp values ('122009','董智强','男','1992-11-23','计算机',50)
--修改数据
--7、将st_cp视图中学号为122009的学生的总学分增加2分。
update st_cp
set tc = tc+2
where stno='122009'
exec sp_rename ‘旧视图’,‘新视图’
--重命名视图
--10、将st_view1视图重命名为st_view2。
exec sp_rename 'st_view1','st_view2'
DROP VIEW view_name
--删除视图
--11、将st_view2视图删除
DROP VIEW st_comm
系统数据类型:
数据类型 | 符号标识 |
---|---|
整数型 | bigint 、int、 smallint、 tinyint |
精确数值型 | decimal、numeric |
浮点型 | float、real |
货币型 | money、smallmoney |
位型 | bit |
字符型 | char、varchar、varchar(MAX) |
Unicode字符型 | nchar、nvarchar、nvarchar(MAX) |
文本型 | text、ntext |
日期时间类型 | datetime、smalltime、date、time、datetime2、datetimeoffset |
二进制型 | binary、varbinary、varbinary(MAX) |
时间戳型 | timestamp |
图像型 | image |
其它 | cursor、sql_variant、table、uniqueidentifer、xml、hierarchyid |
bigint 、int、 smallint、 tinyint的区别:
bigint:占8个字节,64位。
int:占4个字节,32位。从-2^31(-2,147,483,648)到2^31-1(2,147,483,647)的整型数据
smallint:占2个字节,16位。从-2^15(-32,768)到2^15-1(32,767)的整数数据
tinyint:占1个字节,8位。从0到255的整数数据
decimal和numeric存储范围是差不多的,但是最好都用decimal
real型数据的存储大小为4个字节,可精确到小数点后第7位数字。存储范围为从-3.40E+38~-1.18E-38,0和1.18E-38~3.40E+38。
float型的数据存储大小为8个字节,可精确到小数点后第15位数字。存储范围为从-1.79E+308~-2.23E-308,0和2.23E+308~1.79E+308。
money
货币数据值介于 -2^63 (-922,337,203,685,477.5808) 与 2^63 - 1 (+922,337,203,685,477.5807) 之间,精确到货币单位的千分之十。存储大小为 8 个字节。
smallmoney
货币数据值介于 -214,748.3648 与 +214.748,3647 之间,精确到货币单位的千分之十。存储大小为 4 个字节。
nvarchar、varchar的区别:
char
char是定长的,也就是当你输入的字符小于你指定的数目时,char(8),你输入的字符小于8时,它会再后面补空值。当你输入的字符大于指定的数时,它会截取超出的字符。然占用存储空间高,但是查询效率高。
nvarchar(n)
包含 n 个字符的可变长度 Unicode 字符数据。n 的值必须介于 1 与 4,000 之间。字节的存储大小是所输入字符个数的两倍。所输入的数据字符长度可以为零。
varchar[(n)]
长度为 n 个字节的可变长度且非 Unicode 的字符数据。n 必须是一个介于 1 和 8,000 之间的数值。存储大小为输入数据的字节的实际长度,而不是 n 个字节。所输入的数据字符长度可以为零。占用存储空间低,但是查询效率低。
datetime、smalltime、date、time、datetime2、datetimeoffset的区别:
DateTime2(n)表示日期和时间,Date只表示日期,Time(n)只表示时间。
DateTime2(n)数据类型存储日期和时间,它是DateTime的升级版本,由于小数秒n的精度可以自主设置,其存储大小(Storage Size)不固定,DateTime2(n)占用的存储空间和小数秒的精度之间的关系是:
DateTime2(n)内部存储的第一个字节存储精度n,后续的字节用于存储值。
当小数秒的精度 n < 3 时,存储空间是1B(精度)+ B(数据);
当小数秒的精度 n 是 3 - 4 时,存储空间是1B(精度)+ 7B(数据);
当小数秒的精度 n 是 5 - 7 时,存储空间是1B(精度)+ 8B(数据),最大的小数秒精度是7,默认值是7;
DateTime2可以表示比DateTime更精确的时间,默认的数据格式是yyyy-MM-dd hh:mm:ss.nnnnnnn,DateTime2 秒默认的精度是7,即用7位小数表示一秒的精度。
DateTime数据类型存储日期和时间,其存储空间是固定的8个字节,默认的数据格式是yyyy-MM-dd hh:mm:ss.nnn,表示从1753年1月1日到9999年12月31日的日期和时间数据,精确度为3.33毫秒(0.00333秒),也就是说,DateTime表示的日期范围从公元1753年1月1日00:00:00.000 到9999年12月31日23:59:59.997 ,精确到3.33毫秒。
鉴于DateTime的精确度(精确度为3.3毫秒)没有DateTime2(n)高,并且占用的存储空间也比DateTime2(n)高,所以,建议在产品环境中使用DateTime2(n)来代替DateTime类型。
DateTimeOffset(n)数据类型由三部分构成:date、time和 offset(时区偏移),包含了日期、时间和时区数据,其日期和时间使用是本地时间。在本地时间的基础上,使用时区偏移量(offset)来计算UTC时间,因此,DateTimeOffset(n)可以同时表示本地时间和UTC时间,默认的显示文本是:YYYY-MM-DD hh:mm:ss[.nnnnnnn] [{+|-}hh:mm],默认值是1900-01-01 00:00:00 00:00。
DateTimeOffset(n)能够表示的日期、时间和时区范围是:
表示的日期范围是:0001-01-01 到 9999-12-31,
表示的时间范围是:00:00:00 到 23:59:59.9999999,表示的时间精度是100ns,
表示的时区范围是:-14:00 到 +14:00
小数秒的精度会影响变量占用的存储空间的大小:
当小数秒的精度n是 0-2 时,存储大小是8B
当小数秒的精度n是 3-4 时,存储大小是9B
当小数秒的精度n是 5-7 时,存储大小是10B,小数秒的默认精度是7
时区偏移的格式为:[+|-] hh:mm,hh 表示的小时范围是00-14,mm 表示的分钟范围是00-59,把DateTimeOffset时间中的UTC时间 和 时区偏移量 进行算术运算,可以得到本地时间。
自定义数据类型:
SQL server提供了一种称为用户自定义表数据类型的新的用户自定义类型,它可以作为参数提供给语句、存储过程或者函数。
(1)自定义数据类型:
CREATE TYPE type_name
FROM base_type [null丨not null]
# 使用CREATE TYPE 语句创建用户自定义数据类型school_student_num
CREATE TYPE school_student_num
FROM char(4) not null
# 创建用户自定义表数据类型,包含课程表的所有列。
CREATE TYPE course_tabletype
AS TABLE(
cno char(3) not null primary key,
cname char(16) not null,
credit int null,
tno char(6) null
)
(2)使用DROP TYPE语句删除
DROP TYPE type_name
# 删除数据类型school_student_num
DROP TYPE school_student_num
1、常规标识符:
常规标识符就是不需要使用分隔标识符进行分隔的标识符,它以字母、下划线(_)、@或者#开头
2、分隔标识符:
分隔标识符是包含在双引号(“)或者方括号([])内的标识符。
标识符允许的最大长度为128个字符。
1、整型常量:58、+138522、10011011(二进制)、0x1DA(十六进制)
2、实型常量:定点常量(24.7、3795.408)、实型常量(0.7E-3、285.7E5)
3、字符串常量:ASCII字符串常量(‘World’,‘How are you!’)、Unicode字符串常量(N’World’,N’How are you!’)
4、日期时间常量:
字母日期格式:例如‘June 25,2011’
数字日期格式:例如‘9/25/2012’、‘2013-03-11’
未分隔的字符串格式:例如‘20101026’
时间常量:例如‘15:42:47’、‘08:38:AM’
日期时间常量:例如’July 18,2010 16:27:08’
5、货币常量:以“$”作为前缀的整型或实型常量数据,例如$38、$1842906
局部变量由用户定义和使用,局部变量名称前有"@"符号,
语法格式:declare @local_variable data_type
全局变量由系统定义,在名称前面加“@@”符号,用于提供当前的系统信息,T-SQL全局变量作为函数引用,例如@@ERROR返回执行上次执行的T-SQL语句的错误编号,@@CONNECTIONS返回自上次启动SQL Server以来连续或试图连接的次数。
/*
局部变量有两种赋值方式:
1、set赋值
2、select赋值
*/
--1、创建两个局部变量并赋值,然后输出变量值
DECLARE @var1 char(10),@var2 char(20)
set @var1='曹植'
set @var2='是计算机学院的学生'
select @var1 + @var2
--2、创建一个局部变量,在select语句中使用该变量查找计算机学生的学号、姓名、性别。
declare @spec char(12)
set @spe = '计算机'
select stno,stname,stsex
from student
where speciality=@spec
--3、将查询结果赋给局部变量
declare @snm char(8)
set @snm=(select stname from student where stno = '121002')
select @snm
--4、使用select语句给变量赋值
declare @no char(6),@name char(10)
select @no=stno,@name=stname
from student
where speciality='通信'
print @no+''+@name
--5、使用排序规则在查询语句中为变量赋值
declare @no char(6),@name char(10)
select @no=stno,@name=stname
from student
where speciality = '通信'
order by stno desc
print @no+''+@name
--6、使用聚合函数为变量赋值
declare @hg int
select @hg=MAX(grade) from score where grade is not null
print '最高分'
print @hg
加(+)、减(-)、乘(*)、除(/)、取模(%)
运算符 | 运算名称 | 运算规则 |
---|---|---|
& | 按位与 | 两个位均为1时结果为1,否则为0 |
丨 | 按位或 | 只要一个位为1结果就为1,否则为0 |
^ | 按位异或 | 两个位值不同时结果为1,否则为0 |
比较运算符用于测试两个表达式的值是否相同,它的运算结果返回TRUE、FALSE或UNKNOWN
运算符 | 运算名称 | 运算符 | 运算名称 |
---|---|---|---|
= | 相等 | <= | 小于或等于 |
> | 大于 | <> | 不等于 |
< | 小于 | !< | 不小于 |
>= | 大于或等于 | !> | 不大于 |
逻辑运算符用于对某个条件进行测试,运算结果为TRUE或FALSE
运算符 | 运算规则 |
---|---|
AND | 如果两个操作数值都为TRUE,运算结果为TRUE |
OR | 如果两个操作数中有一个为TRUE,运算结果为TRUE |
NOT | 若一个操作数为TRUE,运算结果为FALSE,否则为TRUE |
ALL | 如果每个操作数值都为TRUE,运算结果为TRUE |
ANY | 在一系列操作数中只要有一个为TRUE,运算结果就为TRUE |
BETWEEN | 如果操作数在指定的范围内,运算结果为TRUE |
EXISTS | 如果子查询包含一些行,运算结果为TRUE |
IN | 如果操作数值等于表达式列表中的一个,运算结果为TRUE |
LIKE | 如果操作数与一种模式相匹配,运算结果为TRUE |
SOME | 如果在一系列操作数中有些值为TRUE,运算结果就为TRUE |
通配符 | 说明 |
% | 代表0个或多个字符 |
_ | 代表单个字符 |
[ ] | 指定范围或集合中的任何单个字符,例如范围:[a-f]、[0-9],集合:[abcdef]中任何单个字符 |
[^] | 指定不属于范围或集合的任何单个字符 |
字符串连接运算符通过运算符“+”实现两个或多个字符串的连接运算
在给局部变量赋值的SET和SELECT语句中使用的“=”运算符称为赋值运算符
一元运算符指只有一个操作数的运算符,包含+(正)、-(负) 和~(按位取反)
流程控制语句 | 说明 |
---|---|
BEGIN…END | 将多条语句定义为一个语句块,在执行时该语句块作为个整体来执行 |
IF…ELSE | 条件语句 |
GOTO | 无条件转移语句(不推荐使用) |
WHILE | 循环语句 |
CONTINUE | 用于重新开始下一次循环 |
BREAK | 用于退出最内层的循环 |
RETURN | 无条件返回 |
WAITFOR | 为语句的执行设置延迟 |
IF 条件表达式
A
ELSE
B
IF (SELECT AVG(GRADE) FROM SCORE WHERE CNO = '102') > 80
BEGIN
PRINT '课程:102'
PRINT '平均成绩良好'
END
ELSE
BEGIN
PRINT '课程:102'
PRINT '平均成绩一般'
END
WHILE 条件表达式
循环体
# 显示字符串“Work”中每个字符的ASCII值和字符
DECLARE @PN INT ,@SG CHAR(8)
SET @PN = 1
SET @SG = 'Work'
WHILE @PN <= LEN(@SG)
BEGIN
SELECT ASCII(SUBSTRING(@SG, @PN, 1),CHAR(ASCII(SUBSTRING(@SG, @PN, 1))))
SET @PN = @PN + 1
END
在循环语句中用于退出本层循环,当循环体中有多层循环嵌套时使用BREAK语句只能退出其所在的本层循环。
在循环语句中用于结束本次循环,重新转入循环。
GOTO语句用于实现无条件的跳转,将执行流程转移到标号指定的位置,其语法格式如下:
GOTO lable
# 计算从1~100的和。
DELARE @NM INT ,@I INT
SET @I = 0
SET @NM = 0
LP:
SET @NM = @NM + @I
SET @I = @I + 1
IF @I <= 100
GOTO LP
PRINT '1+2+...+100' + CAST(@NM AS CHAR(10))
RETURN语句用于从查询语句块、存储过程或者批处理中无条件退出,位于RETURN之后的语句将不被执行,其语法格式如下:
RETURN [integer_expression],其中,integer_expression将整型表达式的值返回。
# 判断是否存在学号为121002的学生,如果存在则返回,如果不存在则插入121002的学生信息
IF EXISTS(SELECT * FORM STUDNEGT WHERE STNO = '121002')
RETURN
ELSE
INSERT INTO STUDENT VALUES('121002','周映雪','女','1993-01-12','通信',49)
WAITFOR用于指定语句块、存储过程或者事物执行的 时刻或者等待的时间间隔。语法格式:
WAITFOR {DELAY ‘TIME’ 丨 TIME ‘TIME’}
其中,DELAY‘time’用于指定SQL Server必须等待的时间,TIME‘time’用于指定SQL SERVER等待到某一时刻。
# 设定在早上八点半执行的语句块
BEGIN
WAITFOR TIME '8:30'
SELECT * FROM STUDENT
END
# delay
函数 | 描述 |
---|---|
ABS | 返回数值表达式的绝对值 |
EXP | 返回指定表达式以E为底的指数 |
CEILING | 返回大于或等于数值表达式的最小整数 |
FLOOR | 返回小于或等于数值表达式的最大整数 |
LOG | 返回数值表达式的自然对数 |
LOG10 | 返回数值表达式以10为底的对数 |
POWER | 返回对数值表达式进行幂运算的结果 |
RAND | 返回0~1的一个随机值 |
ROUND | 返回舍入到指定长度或精度的数值表达式 |
SIGN | 返回数值表达式的正号(+)、负号(-)或零(0) |
SQUARE | 返回数值表达式的平方 |
SQRT | 返回数值表达式的平方根 |
--ABS
select ABS(-255)
--EXP
select EXP(2)
--CEILING
select CEILING(3.14)
--FLOOR
SELECT FLOOR(3.14)
--LOG
select LOG(100);
--LOG10
SELECT LOG10(100)
--POWER
select POWER(10,3)
--RAND
select RAND()*10
--ROUND
---SQL四舍五入问题1:
SELECT CAST('123.456' as decimal) ---123 将会得到 123(小数点后面的将会被省略掉)。
---如果希望得到小数点后面的两位。则需要把上面的改为
SELECT CAST('123.456' as decimal(38, 2)) ----123.46---自动四舍五入了!
---SQL四舍五入问题2:
SELECT ROUND(123.75633, 2, 1) ---123.75000
SELECT ROUND(123.75633, 2) ---123.76000
--因为前者在进行四舍五入之前,小数点后已经被截取,保留了2位。
--而后者则没有被截取,四舍五入时自然就会得到123.76000
--ROUND --返回数字表达式并四舍五入为指定的长度或精度。
--ROUND ( numeric_e-xpression , length [ , function ] )
--参数numeric_e-xpression
--精确数字或近似数字数据类型类别的表达式(bit 数据类型除外)。
--length是 numeric_e-xpression 将要四舍五入的精度。length 必须是 tinyint、smallint 或int。
--当 length 为正数时,numeric_e-xpression 四舍五入为 length 所指定的小数位数。
--当 length 为负数时,numeric_e-xpression 则按 length 所指定的在小数点的左边四舍五入。
--function是要执行的操作类型。function 必须是 tinyint、smallint 或 int。如果省略 function 或 function 的值为 0(默认),numeric_e-xpression 将四舍五入。当指定 0 以外的值时,将截断 numeric_e-xpression。
--返回类型返回与 numeric_e-xpression 相同的类型。
--注释ROUND 始终返回一个值。如果 length 是负数且大于小数点前的数字个数,ROUND 将返回 0。
--示例 结果
SELECT ROUND(748.58, -4) --0
--当 length 是负数时,无论什么数据类型,ROUND 都将返回一个四舍五入的 numeric_e-xpression。
--示例 结果
SELECT ROUND(748.58, -1) --750.00
SELECT ROUND(748.58, -2) --700.00
SELECT ROUND(748.58, -3) --1000.00
示例
A. 使用 ROUND 和估计值
下例显示两个表达式,说明使用 ROUND 函数且最后一个数字始终是估计值。
Select ROUND(123.9994, 3), ROUND(123.9995, 3)
Go
下面是结果集:
----------- -----------
123.9990 124.0000
B. 使用 ROUND 和四舍五入的近似值
下例显示四舍五入和近似值。
语句 结果
Select ROUND(123.4545, 2)
123.4500
Select ROUND(123.45, -2)
100.00
C. 使用 ROUND 截断
下例使用两个 Select 语句说明四舍五入和截断之间的区别。第一个语句四舍五入结果。第二个语句截断结果。
语句 结果
Select ROUND(150.75, 0)
151.00
Select ROUND(150.75, 0, 1)
150.00
--SIGN
SELECT SIGN(5) -- 1
SELECT SIGN(-5) -- -1
SELECT SIGN(0)
--SQUARE
SELECT SQUARE(100)
--SQRT
SELECT SQRT(100)
函数 | 描述 |
---|---|
ASCII | ASCII函数,返回字符表达式中最左侧的字符的ASCII代码值 |
CHAR | ASCII代码转换函数,返回指定ASCII代码的字符 |
CHARINDEX | 返回指定模式的起始位置 |
LEFT | 左子串函数,返回字符串中从左边开始指定个数的字符 |
LEN | 字符串函数,返回指定字符串表达式的字符数,其中不包含尾随空格 |
LOWER | 小写字母函数,将大写字符数据转换为小写字符数据后返回字符表达式 |
LTRIM | 删除前导空格字符串,返回删除了前导空格后的字符表达式 |
REPLACE | 替换函数,用第三个表达式替换第一个字符串表达式中出现的所有第二个指定字符串表达式的匹配项 |
REPLICATE | 复制函数,以指定的次数重复字符表达式 |
RIGHT | 右子串函数,返回字符串中从右边开始指定个数的字符 |
RTRIM | 删除尾随空格函数,删除所有尾随空格后返回一个字符串 |
SPACE | 空格函数,返回由重复的空格组成的字符串 |
STR | 数字向字符转换函数,返回由数字数据转换来的字符数据 |
SUBSTRING | 子串函数,返回字符表达式、二进制表达式、文本表达式或图像表达式的一部分 |
UPPER | 大写函数,返回小写字符数据转换为大写的字符表达式 |
--ASCII
SELECT ASCII('A')--65
--CHAR
SELECT CHAR(65)--A
--CHARINDEX
SELECT CHARINDEX('A','ABCA')--1
SELECT CHARINDEX('A','ABCA',2)--4
--LEFT
SELECT LEFT('abcd',3)--abc
--RIGHT
SELECT RIGHT('ABCD',3)--BCD
--LTRIM
SELECT LTRIM(' ABCD ')--ABCD
--RTRIM
SELECT RTRIM(' ABCD ')-- ABCD
--TRIM
SELECT TRIM(' ABCD ')--ABCD
--STR
SELECT 344--344
SELECT STR(344)-- 344
--LOWER
SELECT LOWER('ADCDSss')--adcdsss
--UPPER
SELECT UPPER('ascsdfAASc')--ASCSDFAASC
--REPLACE
SELECT REPLACE('ADDHSSJBDDD','DD','@')--A@HSSJB@D
--REPLICATE
SELECT REPLICATE('ABC',3)--ABCABCABC
--SUBSTRING
DECLARE @N CHAR(10) = 'ABCDEFGH'
SELECT SUBSTRING(@N,1,LEN(@N))--ABCDEFGH
--CHARINDEX
SELECT CHARINDEX('B','ABCDEFGH')--2
函数 | 描述 |
---|---|
DATEADD(datepart,number,date) | 返回给指定日期加上一个时间间隔后的新datetime值 |
DATEDIFF(datepart,startdate,enddate) | 返回跨两个指定日期的日期便结束和时间边界数 |
DATENAME(datepart,date) | 返回表示指定日期的指定日期部门的字符串 |
DATEPART(datepart,date) | 返回表示指定日期的指定日期部分的整数 |
DAY() | 返回一个整数,表示指定日期的datepart部分 |
GETDATE() | 以datetime值得SQL Server2008标准内部格式返回当前系统日期和时间 |
GETUTCDATE() | 返回当前的UTC时间 |
MONTH() | 返回表示指定日期的“月”部分的整数 |
YEAR() | 返回表示指定日期的年份的整数 |
/*
年 yy, yyyy
季度 qq, q
月 mm, m
年中的日 dy, y
日 dd, d
周 wk, ww
星期 dw, w
小时 hh
分钟 mi, n
秒 ss, s
毫秒 ms
微妙 mcs
纳秒 ns
*/
--DATEADD
declare @DATE date = '2016-2-12'
select DATEADD(YY,10,@DATE)
--DATEDIFF
DECLARE @STARTTIME DATE = '2016-02-25'
DECLARE @ENDTIME DATE = '2021-09-01'
SELECT DATEDIFF(DD,@STARTTIME,@ENDTIME)
--DATENAME
DECLARE @R1 DATE = '2016-02-21'
SELECT DATENAME(YY,@R1)
--DATEPART
DECLARE @R2 DATE = '2016-02-21'
SELECT DATEPART(MM,@R2)
--DAY
DECLARE @R3 DATE = '2016-02-21'
SELECT DAY(@R3)
--GETDATE
SELECT GETDATE() AS TIMENAME
--GETUTCDATE
SELECT GETUTCDATE() AS TIMENAME
--MONTH
SELECT MONTH('2016-02-21')
--YEAR
SELECT YEAR('2016-03-18')
函数 | 描述 |
---|---|
COL_NAME(table_id,column_id) | 根据指定的表标识号和列标识号返回列的名称 |
CONVERT(data_type(length),data_to_be_converted,style) | 将一种数据类型的表达式转换为另一种数据类型的表达式 |
CAST | 将一种数据类型的表达式转换为另一种数据类型的表达式 |
CASE | CASE函数用于计算条件列表并返回多个可能的结果表达式之一,有两种形式,一种是简单CASE函数,另一种是搜索型CASE函数。 |
-- COL_NAME
DECLARE @I INT
SET @I=1
WHILE @I <= 6
BEGIN
PRINT COL_NAME(OBJECT_ID('student'),@I)
set @I=@I+1
END
-- CONVERT
100 或者 0 mon dd yyyy hh:miAM (或者 PM)
101 mm/dd/yy
102 yy.mm.dd
103 dd/mm/yy
104 dd.mm.yy
105 dd-mm-yy
106 dd mon yy
107 Mon dd, yy
108 hh:mm:ss
109 或者 9 mon dd yyyy hh:mi:ss:mmmAM(或者 PM)
110 mm-dd-yy
111 yy/mm/dd
112 yymmdd
113 或者 13 dd mon yyyy hh:mm:ss:mmm(24h)
114 hh:mi:ss:mmm(24h)
120 或者 20 yyyy-mm-dd hh:mi:ss(24h)
121 或者 21 yyyy-mm-dd hh:mi:ss.mmm(24h)
126 yyyy-mm-ddThh:mm:ss.mmm(没有空格)
130 dd mon yyyy hh:mi:ss:mmmAM
131 dd/mm/yy hh:mi:ss:mmmAM
SELECT CONVERT(VARCHAR(19),GETDATE())
SELECT CONVERT(VARCHAR(19),GETDATE(),110)
SELECT CONVERT(VARCHAR(19),GETDATE(),106)
SELECT CONVERT(VARCHAR(19),GETDATE(),113)
SELECT CONVERT(VARCHAR(10),GETDATE(),120) --2021-08-18
--
-- COL_NAME
DECLARE @I INT
SET @I=1
WHILE @I <= 6
BEGIN
PRINT COL_NAME(OBJECT_ID('student'),@I)
set @I=@I+1
END
--CONVERT
SELECT CONVERT(VARCHAR(19),GETDATE())
SELECT CONVERT(VARCHAR(19),GETDATE(),110)
SELECT CONVERT(VARCHAR(19),GETDATE(),106)
SELECT CONVERT(VARCHAR(19),GETDATE(),113)
-- CAST
SELECT CAST('102' AS INT)
SELECT CAST('102' AS VARCHAR(10))
SELECT CAST('102' AS decimal)
--求2013年1月1日后200天的日期
SELECT CAST('2013-1-1' AS smalldatetime) + 200 AS '2013.1.1加上200天的日期'
--CASE
SELECT tname AS '姓名',tsex as '性别',
case title
when '教授' then '高级职称'
when '副教授' then '高级职称'
when '讲师' then '中级职称'
when '助教' then '初级职称'
end as '职称类型'
FROM teacher
select stno 学号,cno 课程号,level =
case
when grade>=90 then 'A'
when grade>=80 then 'B'
when grade>=70 then 'C'
when grade>=60 then 'D'
when grade<60 then 'E'
end
from score
where cno='801' and grade is not null
order by stno
用户定义函数分为两类,即标量函数和表值函数。
(1)标量函数:返回值为标量值,即返回一个单一数据值
(2)表值函数:返回值为表值,返回值不是单一数据值,而是由一个表值代表的记录集,即返回table数据类型。
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-OlciD3Fa-1629360943821)(C:\Users\Administrator\AppData\Roaming\Typora\typora-user-images\image-20210816154202246.png)]
CREATE FUNCTION function_name /函数名/
RETURNS return_data_type /返回值类型/
BEGIN
function_body /函数主体/
RETURN scalar_expression /返回值/
END
-- 创建用户定义标量函数spe_av,按专业计算当前学生的平均年龄
IF EXISTS(SELECT NAME FROM SYSOBJECTS WHERE NAME='spe_av' and type='FN')
DROP FUNCTION spe_av
GO
CREATE FUNCTION spe_av(@spe char(12))
RETURNS INT
AS
BEGIN
DECLARE @AV INT
SELECT @AV=(SELECT AVG(DATEDIFF(yy,stbirthday,GETDATE())) FROM student where speciality=@spe)
return @AV
END
declare @spe char(12)
declare @comm int
select @spe='通信'
select @comm=dbo.spe_av(@spe)
print @comm
CREATE FUNCTION function_name
(@parameter parameter_data_type)
RETURNS TABLE
RETURN select_stmt
--定义查询学生姓名、性别、课程号、成绩的内联表函数stu_sco
IF EXISTS(SELECT * FROM SYSOBJECTS WHERE name='stu_sco' and (type='if' or type='tf'))
DROP FUNCTION stu_sco
GO
CREATE FUNCTION stu_sco(@pr char(12))
RETURNS TABLE
AS
RETURN
(
select a.stname,a.stsex,b.cno,b.grade
from student a, score b
where a.stno = b.stno and a.speciality=@pr
)
select * from stu_sco('通信')
游标的基本操作包括声明游标、打开游标、提取数据、关闭游标和删除游标。
1、声明游标
DECLARE cursor_name CURSOR
FOR select_statement
2、打开游标
OPEN cursor_name
3、提取数据
FETCH [NEXT | PRIOR | FIRST | LAST | ABSOLUTE]
FROM cursor_name
4、关闭游标
CLOSE cursor_name
5、删除游标
DEALLOCATE cursor_name
--1、使用游标stu_cur求学生表中第一行的学生情况
--声明游标
DECLARE stu_cur CURSOR
FOR
select stno,stname,tc
from student
--打开游标
OPEN stu_cur
--取数
FETCH NEXT FROM stu_cur
--关闭游标
CLOSE stu_cur
--删除游标
DEALLOCATE stu_cur
--2、使用游标stu_cur2求包含学号、姓名、专业、平均分的学生情况表。
--声明游标
DECLARE @st_no int,@st_name char(8),@st_spe char(8),@st_avg float
DECLARE stu_cur2 CURSOR
FOR select a.stno, a.stname, a.speciality, avg(b.grade)
from student a,score b
where a.stno=b.stno and b.grade > 0
group by a.stno,a.stname,a.speciality
order by a.speciality,a.stno
--打开游标
open stu_cur2
--取数
fetch next from stu_cur2 into @st_no,@st_name,@st_spe,@st_avg
print '学号 姓名 专业 平均分'
print '-------------------------'
while @@FETCH_STATUS=0
/*
0:FETCH语句执行成功
-1:FETCH语句执行失败
-2:被读取的记录不存在
*/
begin
print cast(@st_no as char(8)) + @st_name + @st_spe + ''+cast(@st_avg as char(6))
fetch next from stu_cur2 into @st_no,@st_name,@st_spe,@st_avg
end
--关闭游标
close stu_cur2
--删除游标
deallocate stu_cur2
CREATE PROC procedure_name
[@parameter data_type]
AS <sql_statement>
例子:
IF EXISTS(SELECT * FROM SYSOBJECTS WHERE NAME='stu_score' AND TYPE='p')
DROP PROCEDURE stu_score
GO
CREATE PROCDURE stu_score
AS
SELECT a.stno,a.stsex,a.stname,b.cname,c.grade
FROM student a, course b,score c
WHERE a.stno=c.stno and b.cno=c.cno
ORDER BY a.stno
GO
EXEC module_name [@return_variable=]
[@parameter=]@variable [output]
例子:
--1、不带参数
GO
EXEC sco_avg
GO
--2、带参数
GO
EXEC stu_cou2 @num = '121005'
GO
--3、根据输入参数来判断其返回值
GO
CREATE PROCDURE pr_test(@ipt int = 0)
AS
IF @ipt=0
RETURN 0
IF @ipt>0
RETURN 50
IF @ipt<0
RETURN -50
GO
DECLARE @ret int
exec @ret=pr_test 1
print '返回值为:'
print @ret
(1)sp_help
用于显示存储过程的参数及其数据类型信息
(2)sp_helptext
用于显示存储过程的源代码
(3)sp_depends
用于显示和存储过程相关的数据库对象信息
(4)sp_stored_procedures
用于返回当前数据库中的存储过程列表
--使用相关系统存储过程查看存储过程sco_avg的内容
execute sp_help sco_avg
execute sp_helptext sco_avg
execute sp_depends sco_avg
ALTER PROC procedure_name
[@parameter data_type]
AS <sql_statement>
例子:
IF EXISTS(SELECT * FROM SYSOBJECTS WHERE NAME='stu_score' AND TYPE='p')
DROP PROCEDURE stu_score
GO
ALTER PROCDURE stu_score
AS
SELECT a.stno,a.stsex,a.stname,b.cname,c.grade
FROM student a, course b,score c
WHERE a.stno=c.stno and b.cno=c.cno
ORDER BY a.stno
GO
sp_rename ‘object_name’,‘new_name’
--使用存储过程将存储过程pr_test2重命名为pr_test3
GO
execute sp_rename pr_test2,pr_test3
GO
DROP PROCEDURE procdure_name
--删除存储过程stu_score
DROP PROCDURE stu_score
事务是作为一个整体进行处理的逻辑工作单元,保证多个操作必须全部执行成功,否则必须立即恢复到任何操作执行前的状态,即执行事务的结果是:要么全部将数据所要执行的操作完成,要么全部数据都不修改。
SQL Server通过3种事务模式管理事务:
(1)自动提交事务模式:每条语句都是一个事务。在此模式下,每条T-SQL语句在成功执行后都被自动提交,如果遇到错误,则自动回滚该语句。该模式为系统默认的事务管理模式。
(2)显示事务模式:该模式允许用户定义事务的启动和结束。事务以BEGIN TRANACTION语句显示开始,以COMIT或ROLLBACK语句显示结束。
(3)隐性事务模式:以COMMIT或ROLLBACK语句来提交或回滚事务。在当前事务完后提交或回滚后新事物自动启动。
# 自动提交模式
CREATE ALTER TABLE DROP
INSERT DELETE UPDATE
SELECT
REVOKE GRANT
OPEN FETCH
# 显示事务的开始可使用BEGIN TRANSACTION语句
--语法:
BEGIN {TRAN | TRANSACTION}
{ {transaction_name | @tran_name_variable}
/*transaction_name:分配给事务的名称,必须符合标识符规则,但字符数不超过32
@tran_name_variable:用户定义的含有有效事务名称的变量的名称
*/
[WITH MARK ['description']] /*指定在日志中标记事务*/
}
/*BEGIN TRANSACTION语句的执行使全局变量@@TRANCOUNT的值加1*/
# 隐性事务或显示事务的结束可使用COMMIT TRANSACTION语句
--语法
COMMIT {TRAN | TRANSACTION} [transaction_name | @tran_name_variable]
# 将事务回滚到起点或指定的保存点处,ROLLBACK TRANSACTION
ROLLBACK {TRAN | TRANSACTION}
{transaction_name | @tran_name_variable}
例子:
# 1、建立一个显示事务以显示stsc数据库中的student表的数据
BEGIN TRANSACTION
USE stsc
SELECT * FROM student
COMMIT TRANSACTION
# 2、建立一个显示命名事务以删除课程表和成绩表中的课程号为‘205’的记录行
DECLARE @tran_nm char(20)
SELECT @tran_nm = 'tran_del'
BEGIN TRANSACTION @tran_nm
DELETE FROM course WHERE cno = '205'
DELETE FROM score WHERE cno = '205'
COMMIT TRANSACTION tran_del
# 3、建立一个隐性事务以插入课程表和成绩表中的课程号为‘205’的记录行
SET IMPLICIT_TRANSACTION ON /*启动隐性事务*/
GO
USE stsc
INSERT INTO course VALUES('205','微机原理',4,'204107')
COMMIT TRANSACTION /*提交第一个隐性事务*/
GO
/*第二个隐性事务由SELECT语句启动*/
USE stsc
SELECT COUNT(*) FROM score
INSERT INTO score VALUES ('121001','205',91)
INSERT INTO score VALUES ('121002','205',65)
INSERT INTO score VALUES ('121005','205',85)
COMMIT TRANSACTION /*提交第二个隐性事务*/
GO
SET IMPLICIT_TRANSACTIONS OFF /*关闭隐性事务模式*/
GO
# 建立事务对course表和score表进行操作,使用ROLLBACK TRANSACTION语句标识事务的结束
BEGIN TRANSACTION
USE stsc
INSERT INTO course VALUES('206','数据结构',3,'204103')
INSERT INTO course VALUES('122001','206',75)
INSERT INTO course VALUES('122002','206',94)
INSERT INTO course VALUES('122004','206',88)
ROLLBACK TRANSACTION
BACKUP DATABASE {database_name | @database_name_var} /*被备份的数据库名*/
TO <backup_device> /*备份目标*/
# 使用存储过程创建命名备份设备
sp_addumpdevice [@devtype= ] 'device_type',[@logicalname=]'logical_name',[@physicalname= ]'physical_name'
/*device_type指出介质类型,可以是DISK或TYPE,DISK表示磁盘文件,TAPE表示是磁带设备;
logical_name和physical_name分别是逻辑名和物理名
*/s
例子:
# 创建一个命名备份设备testbp,并将数据库mystsc完整备份到该设备。
EXEC sp_addumpdevice 'disk','testbp','E:\tmpsql\testbp.bak'
BACKUP DATABASE mystsc TO testbp
在进行差异数据库备份时将备份从最近的完整数据库备份后发生变化的数据部分,对于需要频繁修改的数据库,该备份类型可以缩短备份和恢复的时间。
BACKUP DATABASE {database_name | @database_name_var}
READ_WRITE_FILEGROUPS
TO <backup_device>
{
WITH
[DIFFERENTIAL]
/*其余选项与数据库的完全备份相同*/}
例子:
# 创建临时备份设备并在所创建的临时备份设备上对数据库mystsc进行差异备份
BACKUP DATABAE mystsc TO
DISK = 'E:\tmpsql\testbpl.bak'
WITH DIFFERENTIAL
事务日志备份用于记录前一次数据库备份或事务日志备份后数据库所做出的的改变,事务日志备份需要在一次完全数据库备份后进行,这样才能将事务日志文件和数据库备份一起用于恢复。在进行事务日志备份时系统进行的操作如下:
(1)将事务日志中从前一次成功备份结束位置开始到当前事务日志结尾处的内容进行备份。
(2)标识事务日志中活动部分的开始,所谓事务日志的活动部分指从最近的检查点或最早的打开位置开始至事务日志的结尾处。
进行事务日志备份使用BACKUP LOG语句。
语法格式:
BACKUP LOG {database_name | @database_name_var } /*指定被备份的数据库名*/
{
TO <back_up_device>
}
例子:
# 创建一个命名备份设备myslogbk备份mystsc数据库的事务日志
EXEC sp_addumpdevice 'disk','myslogbk','E:\nmsql\myslogbk.bak'
BACKUP LOG mystsc TO myslogbk
语法格式:
BACKUP DATABASE {database_name | @database_name_var }
<file or filegroup > /*指定文件或文件组名*/
TO <backup_device>
语法格式:
RESTORE DATABASE {database_name | @database_name var} /*指定被还原的目标数据库*/
[FROM <backup_device>] /*指定备份设备*/
例子:
# 创建命名备份设备stscbk并备份数据库mystsc到stscbk后使用RESTORE语句从备份设备stscbk中完整恢复数据库mystsc
GO
EXEC sp_addumpdevice 'disk','stscbk','E:\nmsql\stscbk.bak'
BACKUP DATABASE mystsc TO stscbk
RESTORE DATABASE mystsc FROM stscbk
WITH FILE = 1,REPLACE
GO
这是将数据库的部分内容还原到另一个位置,以使损坏或丢失的数据可复制至数据库。
语法格式:
RESTORE DATABASE {databasae_name | @database_name_var}
[FROM <backup_device>]
WITH
PARTIAL, NORECOVERY
恢复事务日志可以将数据库恢复到指定的时间点
语法格式:
RESTORE LOG {database_name | @database_name_var}
[FROM <backup_device>]
若某个或某些文件被破坏或者被误删除,可以从文件或文件组备份中进行恢复,而不必进行整个数据库的恢复。
语法格式:
RESTORE DATABASE {database_name | @database_name_var}
<file or filegroup>
[FROM <backup_device>]
WITH
{
[RECOVERY | NORECOVER]
[,<general_WITH_options>]
}
从备份表中更新字段到正式表中,使用UPDATE批量更新大量的数据,会出现效率低下,有时候甚至卡死的情况,后面通过使用MERGE INTO代替UPDATE执行批量更新,会提升执行效率。
语法格式:
MERGE INTO table_name alias1 /*table_name指的是更新的表*/
USING (table|view|sub_query) alias2 /*USING()里边的指的是数据来源表/视图/子查询结果集*/
ON (join condition) /*condition指的是连接条件,如果满足连接条件,set 字段1=值1,字段2=值2...,如果*/
WHEN MATCHED THEN /*连接条件不满足,则停止更新进行插入*/
UPDATE
SET col1 = col1_val1,
col2 = col2_val2
WHEN NOT MATCHED THEN
INSERT (column_list) VALUES (colun_values);
例子:
# 创建临时表
create table #temp(stno varchar(16),stname varchar(16),stsex varchar(16),stbirthday date,speciality varchar(16),tc int)
select * from #temp
# 在临时表中插入学号
insert into #temp(stno) select stno from student
# 在临时表中插入姓名、性别、出生日期、专业
merge into #temp target
using (select s.stno,s.stname,s.stsex,s.stbirthday,s.speciality from student s) source
on (target.stno = source.stno)
when matched then
update
set target.stname = source.stname,
target.stsex = source.stsex,
target.stbirthday = source.stbirthday,
target.speciality = source.speciality;
row_number()
OVER (
PARTITION BY COL1
ORDER BY COL2)
表示根据COL1分组,在分组内部根据 COL2排序,而此函数计算的值就表示每组内部排序后的顺序编号(组内连续的唯一的)
举例:
create table employee (empid int ,deptid int ,salary decimal(10,2))
insert into employee values(1,10,5500.00)
insert into employee values(2,10,4500.00)
insert into employee values(3,20,1900.00)
insert into employee values(4,20,4800.00)
insert into employee values(5,40,6500.00)
insert into employee values(6,40,14500.00)
insert into employee values(7,40,44500.00)
insert into employee values(8,50,6500.00)
insert into employee values(9,50,7500.00)
执行结果:
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-xGG1jd4v-1629360943822)(C:\Users\Administrator\AppData\Roaming\Typora\typora-user-images\image-20210818131448564.png)]
使用row_number()over():
SELECT *,
Row_Number() OVER
(partition by deptid
ORDER BY salary desc) rank
FROM employee
执行结果:
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Tdcemiz0-1629360943825)(C:\Users\Administrator\AppData\Roaming\Typora\typora-user-images\image-20210818131703511.png)]
STUFF()函数用于删除指定长度的字符,并可以在制定的起点处插入另一组字符。
语法格式: STUFF (character_expression, start, length, character_expression)
character_expression 一个字符数据表达式。character_expression 可以是常量、变量,也可以是字符列或二进制数据列。
start 一个整数值,指定删除和插入的开始位置。如果start 或 length 为负,则返回空字符串。如果start比第一个character_expression长,则返回空字符串。start可以是bigint类型。
length 一个整数,指定要删除的字符数。如果length比第一个character_expression长,则最多删除到最后一个character_expression中的最后一个字符。length可以是bigint类型。
返回类型 如果character_expression 是受支持的字符数据类型,则返回字符数据。如果character_expression是一个受支持的binary数据类型,则返回二进制数据。
# 例子
SELECT STUFF('ABCDEF',2,3,'IJKLMN')
# 结果
AIJKLMNEF
详细见解:[http://www.360doc.com/content/20/0214/22/11881101_892070529.shtml]
例如:
select * from employee
结果显示:
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-oS5mPOjF-1629360943829)(C:\Users\Administrator\AppData\Roaming\Typora\typora-user-images\image-20210819102757880.png)]
select * from employee for xml path
结果显示:
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-3q0CvY7c-1629360943830)(C:\Users\Administrator\AppData\Roaming\Typora\typora-user-images\image-20210819102950795.png)]
进行调整修改后:
select empid 员工编号,deptid 部门编号,salary 薪水 from employee for xml path('')
结果显示:
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-spxPtmco-1629360943832)(C:\Users\Administrator\AppData\Roaming\Typora\typora-user-images\image-20210819103506701.png)]
返回由逻辑测试确定的两个数值或字符串值之一。
数字 IIF(Logical EXPression, Numeric Expression 1,Numeric Expression 2)
如果Logical Expression取值为TRUE,则此函数返回Numeric Expression 1,否则返回Numeric Expression 2
字符串 IIF(Logical EXPression, String Expression 1,String Expression 2)
如果Logical Expression取值为TRUE,则此函数返回String Expression 1,否则返回String Expression 2
注释
只有当逻辑值为零时,才认为该表达式是FAlSE,任何其它值都被解释为TRUE。
举例:
select IIF(1<>2,'yes','no') --yes
select IIF(1<2,1,2) --1
select IIF(1>2,1,'2') --2
给定两个参数Expression1和Expression2,如果两个参数相等,则返回NULL;否则就返回第一个参数。
等价于:Case WHEN Expression1=Expression2 Then NULL ELSE Expression1。
select NULLIF(1,1) --NULL
select NULLIF(1,2) --1
select NULLIF(2,1) --2
给定两个参数Expression1和Expression2,如果Expression1是NULL,那么返回Expression2,否则返回Expression1。
等价于:Case WHEN Expression1 is NULL Then Expression2 ELSE Expression1。
select ISNULL(NULL,1) --1
select ISNULL(2,1) --2
ISNUMERIC函数的作用是确定表达式是否为一个有效的数字类型。
语法:
ISNUMERIC ( expression )
如果输入表达式的计算值为有效的整数、浮点数、money 或 decimal 类型时,ISNUMERIC 返回 1;否则返回 0。返回值为 1 时,指示可将 expression 至少转换为上述数值类型中的一种。
select
isnumeric('1e-2'), --1
isnumeric('1e+2'), --1
isnumeric('1e2'), --1
isnumeric('1.1'), --1
isnumeric('-1.1'), --1
isnumeric('+1.1'), --1
isnumeric('$12'), --1
isnumeric('¥12'), --1
isnumeric('acb'), --0
isnumeric('a41') --0
raiserror 的作用: raiserror 是用于抛出一个错误
语法格式:
RAISERROR ( { msg_id | msg_str | @local_variable }
{ ,severity ,state }
[ ,argument [ ,...n ] ]
)
[ WITH option [ ,...n ] ]
第一个参数:{ msg_id | msg_str | @local_variable }
msg_id:表示可以是一个sys.messages表中定义的消息代号;
使用 sp_addmessage 存储在 sys.messages 目录视图中的用户定义错误消息号。
用户定义错误消息的错误号应当大于 50000。
msg_str:表示也可以是一个用户定义消息,该错误消息最长可以有 2047 个字符;
(如果是常量,请使用N'xxxx',因为是nvarchar的)
当指定 msg_str 时,RAISERROR 将引发一个错误号为 5000 的错误消息。
@local_variable:表示也可以是按照 msg_str 方式的格式化字符串变量。
第二个参数:severity 实际设计中默认为16
用户定义的与该消息关联的严重级别。(这个很重要)
任何用户都可以指定 0 到 18 之间的严重级别。
[0,10]的闭区间内,不会跳到catch;
如果是[11,19],则跳到catch;
如果[20,无穷),则直接终止数据库连接;
第三个参数:state
如果在多个位置引发相同的用户定义错误,
则针对每个位置使用唯一的状态号有助于找到引发错误的代码段。
介于 1 至 127 之间的任意整数。(state 默认值为1)
当state 值为 0 或大于 127 时会生成错误!
第四个参数:argument
用于代替 msg_str 或对应于 msg_id 的消息中的定义的变量的参数。
第五个参数:option
错误的自定义选项,可以是下表中的任一值:
LOG :在错误日志和应用程序日志中记录错误;
NOWAIT:将消息立即发送给客户端;
SETERROR:将 @@ERROR 值和 ERROR_NUMBER 值设置为 msg_id 或 50000;
--示例1
DECLARE @raiseErrorCode nvarchar(50)
SET @raiseErrorCode = CONVERT(nvarchar(50), YOUR UNIQUEIDENTIFIER KEY)
RAISERROR('%s INVALID ID. There is no record in table',16,1, @raiseErrorCode)
--示例2
RAISERROR (
N'This is message %s %d.', -- Message text,
10, -- Severity,
1, -- State,
N'number', -- First argument.
5 -- Second argument.
);
-- The message text returned is: This is message number 5
型时,ISNUMERIC 返回 1;否则返回 0。返回值为 1 时,指示可将 expression 至少转换为上述数值类型中的一种。
select
isnumeric('1e-2'), --1
isnumeric('1e+2'), --1
isnumeric('1e2'), --1
isnumeric('1.1'), --1
isnumeric('-1.1'), --1
isnumeric('+1.1'), --1
isnumeric('$12'), --1
isnumeric('¥12'), --1
isnumeric('acb'), --0
isnumeric('a41') --0
raiserror 的作用: raiserror 是用于抛出一个错误
语法格式:
RAISERROR ( { msg_id | msg_str | @local_variable }
{ ,severity ,state }
[ ,argument [ ,...n ] ]
)
[ WITH option [ ,...n ] ]
第一个参数:{ msg_id | msg_str | @local_variable }
msg_id:表示可以是一个sys.messages表中定义的消息代号;
使用 sp_addmessage 存储在 sys.messages 目录视图中的用户定义错误消息号。
用户定义错误消息的错误号应当大于 50000。
msg_str:表示也可以是一个用户定义消息,该错误消息最长可以有 2047 个字符;
(如果是常量,请使用N'xxxx',因为是nvarchar的)
当指定 msg_str 时,RAISERROR 将引发一个错误号为 5000 的错误消息。
@local_variable:表示也可以是按照 msg_str 方式的格式化字符串变量。
第二个参数:severity 实际设计中默认为16
用户定义的与该消息关联的严重级别。(这个很重要)
任何用户都可以指定 0 到 18 之间的严重级别。
[0,10]的闭区间内,不会跳到catch;
如果是[11,19],则跳到catch;
如果[20,无穷),则直接终止数据库连接;
第三个参数:state
如果在多个位置引发相同的用户定义错误,
则针对每个位置使用唯一的状态号有助于找到引发错误的代码段。
介于 1 至 127 之间的任意整数。(state 默认值为1)
当state 值为 0 或大于 127 时会生成错误!
第四个参数:argument
用于代替 msg_str 或对应于 msg_id 的消息中的定义的变量的参数。
第五个参数:option
错误的自定义选项,可以是下表中的任一值:
LOG :在错误日志和应用程序日志中记录错误;
NOWAIT:将消息立即发送给客户端;
SETERROR:将 @@ERROR 值和 ERROR_NUMBER 值设置为 msg_id 或 50000;
--示例1
DECLARE @raiseErrorCode nvarchar(50)
SET @raiseErrorCode = CONVERT(nvarchar(50), YOUR UNIQUEIDENTIFIER KEY)
RAISERROR('%s INVALID ID. There is no record in table',16,1, @raiseErrorCode)
--示例2
RAISERROR (
N'This is message %s %d.', -- Message text,
10, -- Severity,
1, -- State,
N'number', -- First argument.
5 -- Second argument.
);
-- The message text returned is: This is message number 5