QL Server 实用脚本

时间:2022-02-13 09:09:01
use MyFirstDB;

-- 主要内容
-- SQL Server 实用脚本
-- 1、case语句
-- 2、子查询
-- 3、连接查询
-- 4、脚本变量与流程控制(选择与循环等)
-- 5、事务
-- 6、存储过程
-- 7、触发器 ---------------------------------
-- case 语句
-- 类似于C#中的三元表达式,好比n元表达式
-- 语法
-- 1)写在哪里? 在sql语句中需要值(标量)的地方
-- 2)
-- if-else结构
/*
case
when 条件then 值
when 条件then 值
...
else 默认值
end
*/
select
stuName
, case
when stuSex='m' then '男'
when stuSex='f' then '女'
else '其他'
end as 性别
, datediff(YEAR, stuBirthdate, GETDATE()) as 年龄
--,*
from
TestDataBase..Student
where
stuId<20;
--
-- switch-case结构
/*
case 字段
when 值then 结果
when 值 then 结果
...
else 默认值
end
*/
select
DATEDIFF(YEAR, stuBirthdate, GETDATE()) as 年龄
,case stuSex
when 'm' then '男'
when 'f' then '女'
else '其他'
end as 性别
, * from
TestDataBase..Student
where
stuId<20;
-- 练习
create table test
(
number varchar(10),
amount int
)
insert into test(number,amount) values('RK1',10)
insert into test(number,amount) values('RK2',20)
insert into test(number,amount) values('RK3',-30)
insert into test(number,amount) values('RK4',-10) --
select * from test; select number, '收入', '支出' from test; select
number
, case when amount>=0 then amount else 0 end as '收入'
, case when amount<0 then abs(amount) else 0 end as '支出'
from Test
-------------------------------------
create table Score
(
学号 nvarchar(10),
课程 nvarchar(10),
成绩 int
) insert into Score values('','语文',87);
insert into Score values('','数学',79);
insert into Score values('','英语',95);
insert into Score values('','语文',69);
insert into Score values('','数学',84);
--
select * from Score;
-- 表的透视变换ANSI-SQL的做法
select
学号
, sum(case when 课程='语文' then 成绩 else 0 end) as '语文'
, sum(case when 课程='数学' then 成绩 else 0 end) as '数学'
, sum(case when 课程='英语' then 成绩 else 0 end) as '英语'
from
Score
group by
学号
-- T-SQL2008 透视变换与你透视变换PIvote UnPivote
---------------------------- -- 2、子查询
-- 什么是子查询?
-- 在一个查询中,一个查询的结果作为另一个查询的条件,那么这个
-- 查询称为子查询,这个使用条件的查询称为外部查询
-- 查询“纪明杰”的考试成绩
select stuId from TestDataBase..Student where stuName='纪明杰';
select * from TestDataBase..Score where stuId=1; select * from TestDataBase..Score where stuId =
(select top 1 stuId from TestDataBase..Student where stuName='纪明杰'); -- 查询“濮阳语儿”
-- select * from TestDataBase..Student order by stuId;
select * from TestDataBase..Score where stuId in
(select stuId from TestDataBase..Student where stuName='濮阳语儿'); -- 标量子查询与多值子查询
-- 独立子查询 -- 相关子查询
-- 查询"纪明杰"的考试平均分(三个科目的综合求avg)
select
stuName
, (
select avg(testBase+testBeyond+testPro)
from TestDataBase..Score
where stuId = t.stuId -- 此时子查询需要使用外部查询的stuId
)'分数' -- 只需要放至id号位纪明杰同学的分数即可
from
TestDataBase..Student as t
where
stuName='濮阳语儿'; -- 3、连接查询(表连接)
-- 为什么要使用这个,这个是什么
-- 就是将多张表合并成一张表
-- 查询"纪明杰"的信息
-- 个人信息(Student)、分数信息(Score)、课程信息(Course)
select
t1.*
, t2.className, t2.classDescription
, t3.testBase,t3.testBeyond,t3.testPro
from
TestDataBase..Student as t1
inner join
TestDataBase..Course as t2
on t1.classId = t2.classId
inner Join
(select
stuId
, avg(testBase) as TestBase
, AVG(testBeyond) as testBeyond
, avg(testPro) as testPro
from
TestDataBase..Score
group by
stuId) as t3
on t1.stuId = t3.stuId
where
t1.stuName = '纪明杰'; -- 连接操作的分类:交叉连接、内链接、外连接(左外、右外、全连接) --
select * into TestDataBase..Employee from
(values (1, '马伦', 2),
(2, '赵晓虎', 1),
(3, '杨中科', null)
) as Employee(empId, empName, titleId); select * into TestDataBase..Title from
(values
(1, '讲师')
, (2, '学科负责人')
) as title(titleId, titleName); select * from TestDataBase..Employee;
select * from TestDataBase..Title; select * from
TestDataBase..Employee
cross join
TestDataBase..Title; select * from (select * from
(values (1, '马伦', 2),
(2, '赵晓虎', 1),
(3, '杨中科', null)
) as Employee(empId, empName, titleId)) as t1
cross join
(select * from
(values
(1, '讲师')
, (2, '学科负责人')
) as title(titleId, titleName)) as t2; ------------------------------
-- numTbl(num) 1-10000
create table numTbl
(
num int not null
);
insert into numTbl(num) values(0),(1),(2),(3),(4),(5),(6),(7),(8),(9); select * from numTbl; select
t1.num + t2.num * 10 + t3.num*100 + t4.num * 1000 + t5.num*10000 + 1 as n
from
numTbl as t1
cross join
numTbl as t2
cross join
numTbl as t3
cross join
numTbl as t4
cross join
numTbl as t5
order by
n select * from sys.objects; -- 内链接的实现
use TestDataBase;
select stuId, stuName from Student;
select * from Course; select t1.stuId, t1.stuName, t2.className from
Student as t1
inner join
Course as t2
on t1.classId = t2.classId
order by
t1.stuId; -- 语法注意
-- ANSI-SQL 89
select * from Employee, Title;
select * from Employee t1, Title t2 where t1.titleId=t2.titleId;
-- ANSI-SQL 92 -- 外连接
select * from
Employee as t1
full join
Title as t2
on t1.titleId = t2.titleId; -- 4、表表达式
-- 派生表、公用表表达式(CTE)、视图(、内联表值函数)
-- 派生表就是由一个查询得到的结果集,作为数据源被查询,这个结果集就是派生表
/*
select
*
from -- 学生的完整信息
(select * from ...) as t
where
t.stuName='濮阳语儿';
*/
-- 使用派生表实现分页
select * from TestDataBase..Student order by stuId;
-- 第一页,每页十条
select top 10 * from Student order by stuId;
-- 第二页,每页十条(11-20)
-- 第三页(21-30)
select top 10
*
from
Student
where
stuId not in(
select top ((@pageIndex-1) * @pageCount) stuId from Student order by stuId
)
order by
stuId;
-- between and
select * from Student where stuId between 1 and 10;
select * from Student where stuId between 11 and 20;
select * from Student where stuId between 21 and 30;
select * from Student where stuId between (@pageIndex - 1) * @pageCount + 1 and @pageIndex * @pageCount; -- 显示第n也,每页显示m条记录 select * from
( -- 派生表
select
ROW_NUMBER() over(order by stuId) as num
, *
from
Student
) as t
where
t.num between (n-1)*m + 1 and n * m; -- 公用表表达式(CTE common table expression)
-- 为什么要有这个东西
--with 别名
--as
--(
-- 结果集
--)
--查询 with t
as
(
select
ROW_NUMBER() over(order by stuId) as num
, stuName
, stuSex
, stuBirthdate
, stuStudydate
, stuAddress
, stuEmail
, stuPhone
, stuIsDel
, stuInputtime
, classId
from
Student
where
stuIsDel = 0
)
select
t.num as 编号
, t.stuName as 姓名
, datediff(year, t.stuBirthdate, getdate()) as 年龄
, convert(varchar, t.stuStudydate, 111) as 入学时间
, t.stuEmail as 电子邮件 from
t
where
t.num between (3-1)*10 + 1 and 3 * 10; -- 视图(view)
-- 为什么要使用视图
-- 视图的本质,是对系统中具体的物理表的复杂查询的一个映射,其本质还是一个查询
-- 可以认为是一个查询的别名
/*
create view 架构.vw_视图名
as
结果集
*/
go
create schema pub authorization dbo;
go
create view pub.vw_StuInfo
as
select
ROW_NUMBER() over(order by stuId) as num
, stuName
, stuSex
, stuBirthdate
, stuStudydate
, stuAddress
, stuEmail
, stuPhone
, stuIsDel
, stuInputtime
, className
, classDescription
from
Student as t1
inner join
Course as t2
on t1.classId = t2.classId
where
t1.stuIsDel = 0
;
go select * from vw_StuInfo where num between 11 and 20; -- 在使用非常复杂的sql语句查询数据的时候
-- 将查询进行打包(记录的sql语句,是结果集),取了一个名字
-- 在查询的时候就不需要使用非常复杂的sql语句了
-- 直接使用这个结果集 select * from pub.vw_StuInfo; -- 5、脚本变量与流程控制(选择与循环等)
-- 变量的使用(先声明,在赋值,后使用)
declare @varible varchar(10); -- 声明变量
-- set @varible = '测试数据'; -- 赋值
-- set @varible = (select '测试的数据'); -- 标量子查询赋值
select @varible=stuName from Student where stuId = 3; select @varible; -- 使用变量 -- 选择结构
if ()
begin
语句
end
else if ()
begin
end
else
begin
end -- 循环结构
while(表达式)
begin
end -- 求到中所有偶数的和
declare @sum int;
declare @i int;
select @sum=0, @i=0;
while @i <= 100
begin
if (@i % 2 = 0)
begin
set @sum = @sum + @i;
end
set @i = @i + 1;
end
select @sum; -- 6、事务
--事务
create table bank
(
cId char(4) primary key,
balance money --余额
) alter table bank
add constraint CH_balance check(balance >=10) go
--delete from bank
insert into bank values('',1000)
insert into bank values('',10)
go select * from bank; update bank set balance=balance - 1000 where cid=''
update bank set balance=balance + 1000 where cid='' -- 如何使用事务?
-- 在SQL Server中每一条sql语句默认为一个事务
insert into Employee(empId, empName, titleId) values
(4, '赵晓雪', null),
(5, '赵晓飞雪', null),
(6, '赵大雪', null)
-- 原子性 -- 手动使用事务
begin transaction
写代码
-- 提交事务,让这里的代码全部生效
commit transaction
-- 回滚事务,这里所有的操作无效
rollback transaction begin transaction delete from Score where Score.testId > 1;
delete from Student where stuId > 1;
delete from Course where classId > 1; rollback transaction select * from Student;
select * from Course;
select * from Score; ---------------------
-- @变量名 自定义变量
-- @@系统变量
@@error -- 记录最近一次sql语句执行的状态码,如果大于表示这条有错误 select @@ERROR; begin transaction
declare @myError int;
set @myError = 0;
update bank set balance=balance - 500 where cid=''
set @myError = @myError + @@ERROR;
update bank set balance=balance + 500 where cid=''
set @myError = @myError + @@ERROR;
if @myError > 0
begin
rollback transaction
end
else
begin
commit transaction
end select * from bank; begin transaction
begin try
update bank set balance=balance + 600 where cid=''
update bank set balance=balance - 600 where cid=''
commit transaction
end try
begin catch
rollback transaction
end catch -- 事务的特征:原子性、持久性、隔离性、一致性
-- 隔离级别、快照、锁定排查 -- 7、存储过程
-- 为什么需要存储过程?
-- 如何使用?(存储过程好比C#中的方法)
use master;
exec sp_detach_db 'mfb'; CREATE DATABASE Archive
ON (FILENAME = 'd:\db\hei14\MyFirstDB.mdf')
FOR ATTACH ;
GO
exec sp_renamedb 'MyFirstDB', 'mfb' -- 存储过程语法 usp_
--create procedure 存储过程的名字
--@变量类型[= 默认值] [output]
--,@变量类型[= 默认值] [output]
--,@变量类型[= 默认值] [output]
--as
--begin
-- 。。。
--end -- 转账,每次转元
go
use TestDataBase;
go
create proc usp_转账
as
begin
begin transaction
begin try
update bank set balance=balance - 100 where cid=''
update bank set balance=balance + 100 where cid=''
commit transaction
end try
begin catch
rollback transaction
end catch
end;
go
exec usp_转账;
select * from bank; go
create proc usp_转账
@from char(4)
, @to char(4)
, @money money
as
begin
begin transaction
begin try
update bank set balance=balance - @money where cid=@from
update bank set balance=balance + @money where cid=@to
commit transaction
end try
begin catch
rollback transaction
end catch
end;
go
-- 调用带有参数的存储过程
exec usp_转账 '', '', 200.00 exec usp_转账 @to='', @from='', @money=1000 select * from bank; go
create proc usp_转账
@from char(4)
, @to char(4)
, @money money
, @isSuccess int output
as
begin
begin transaction
begin try
update bank set balance=balance - @money where cid=@from
update bank set balance=balance + @money where cid=@to
commit transaction
set @isSuccess = 1;
end try
begin catch
rollback transaction
set @isSuccess = 0;
end catch
end;
go -- 需要一个变量
declare @res int
-- exec usp_转账'0001', '0002', 500, @res output;
exec usp_转账 @isSuccess=@res output, @to='', @from='', @money=500 select @res; select * from bank; -- 使用C#执行存储过程的步骤:
-- 1、将sql语句变成存储过程的名字
-- 2、将SqlCommand对象的CommandType设置为StoredProcedure exec sp_help; -- 8、触发器
-- 什么是?
-- 是存储过程,类似于c#中的事件
-- 什么时候使用?
-- 跨数据库表等对象所做的验证
-- 监视数据变动
-- 语法?
-- 触发器的分类:after触发器、instead of触发器
-- 针对增删改操作进行触法 -- 语法
/*
create trigger tr_触发器名字on 表名
after | instead of
update | delete | insert
as
begin
代码
end
*/ -- inserted表deleted表
-- 是在增加数据、删除数据或修改数据的过程中临时创建的表 -- 如何得到刚刚插入数据的id号 select * from Employee;
insert into Employee(empName) values('赵晓虎'); insert into Employee(empName) output inserted.* values('赵晓'); go
create trigger tr_永远删除不了的数据 on Employee
after
delete
as
-- 将删除的数据插入回来
insert into Employee(empName, titleId)
select empName, titleId from deleted;
go delete from Employee; truncate table Employee; select SUSER_SNAME(); go
create trigger tr_watch_insert on Employee
after
insert
as
begin
declare @res varchar(500);
set @res = '用户''' + suser_name() + '''添加数据:';
set @res = @res + (select empName from inserted);
print @res;
end select * from Employee; insert into Employee(empName) values('wcw'); -- 什么是?
-- 干什么用?
-- 语法