--1.inner join :能够找到两个表中建立连接字段值相等的记录 --查询学员信息显示班级名称 select Student.StudentNo,Student.StudentName,grade.classname from Student inner join grade on Student.ClassId=grade.ClassId
--左连接: 关键字前面的表是左表,后面的表是右表 --左连接可以得到左表所有数据,如果建立关联的字段值在右表中不存在,那么右表的数据就以null值替换 select PhoneNum.*,PhoneType.* from PhoneNum left join PhoneType on PhoneNum.pTypeId=PhoneType.ptId
--右连接: 关键字前面的表是左表,后面的表是右表 --右连接可以得到右表所有数据,如果建立关联的字段值在右左表中不存在,那么左表的数据就以null值替换 select PhoneNum.*,PhoneType.* from PhoneNum right join PhoneType on PhoneNum.pTypeId=PhoneType.ptId
--full join :可以得到左右连接的综合结果--去重复 select PhoneNum.*,PhoneType.* from PhoneNum full join PhoneType on PhoneNum.pTypeId=PhoneType.ptId
一种处理机制。以事务处理的操作,要么都能成功执行,要么都不执行
事务的四个特点 ACID:
A:原子性:事务必须是原子工作单元;对于其数据修改,要么全都执行,要么全都不执行。它是一个整体,不能再拆分
C:一致性:事务在完成时,必须使所有的数据都保持一致状态。。某种程度的一致
I:隔离性:事务中隔离,每一个事务是单独的请求将单独的处理,与其它事务没有关系,互不影响
D:持久性:如果事务一旦提交,就对数据的修改永久保留使用事务:
将你需要操作的sql命令包含在事务中
1.在事务的开启和事务的提交之间
2.在事务的开启和事务的回滚之间
三个关键语句:
开启事务:begin transaction
提交事务:commit transaction
回滚事务:rollback transaction
declare @num int =0 --记录操作过程中可能出现的错误号 begin transaction update bank set cmoney=cmoney-500 where name='aa' set @num=@num+@@ERROR --说明这一句的执行有错误 但是不能在语句执行的过程中进行提交或者回滚 --语句块是一个整体,如果其中一句进行了提交或者回滚,那么后面的语句就不再属于当前事务, --事务不能控制后面的语句的执行 update bank set cmoney=cmoney+500 where name='bb' set @num=@num+@@ERROR select * from bank if(@num<>0 ) --这个@@ERROR只能得到最近一一条sql语句的错误号 begin print '操作过程中有错误,操作将回滚' rollback transaction end else begin print '操作成功' commit transaction end --事务一旦开启,就必须提交或者回滚 --事务如果有提交或者回滚,必须保证它已经开启
视图就是一张虚拟表,可以像使用子查询做为结果集一样使用视图
select * from vw_getinfo
使用代码创建视图
语法:
create view vw_自定义名称
as
查询命令
go
--查询所有学员信息 if exists(select * from sysobjects where name='vw_getAllStuInfo') drop view vw_getAllStuInfo go --上一个批处理结果的标记 create view vw_getAllStuInfo as --可以通过聚合函数获取所以记录数 select top (select COUNT(*) from Student) Student.StudentNo,Student.StudentName,grade.ClassId,grade.classname from Student inner join grade on Student.ClassId=grade.ClassId order by StudentName --视图中不能使用order by --select * from grade --只能创建一个查询语句 --delete from grade where ClassId>100 --在视图中不能包含增加删除修改 go --使用视图。。就像使用表一样 select * from vw_getAllStuInfo --对视图进行增加删除和修改操作--可以对视图进行增加删除和修改操作,只是建议不要这么做:所发可以看到:如果操作针对单个表就可以成功,但是如果 多张的数据就会报错:不可更新,因为修改会影响多个基表。 update vw_getAllStuInfo set classname='asdas' ,studentname='aa' where studentno=1
触发器:执行一个可以改变表数据的操作(增加删除和修改),会自动触发另外一系列(类似于存储过程中的模块)的操作。
语法:
create trigger tr_表名_操作名称
on 表名 after|instead of 操作名称
as
go
if exists(select * from sysobjects where name='tr_grade_insert') drop trigger tr_grade_insert go create trigger tr_grade_insert on grade for insert ---为grade表创建名称为tr_grade_insert的触发器,在执行insert操作之后触发 as declare @cnt int set @cnt = (select count(*) from student) select * ,@cnt from student select * from grade go --触发器不是被调用的,而是被某一个操作触 发的,意味着执行某一个操作就会自动触发 触发器 insert into grade values('fasdfdssa') ---替换触 发器:本来需要执行某一个操作,结果不做了,使用触 发器中的代码语句块进行替代 if exists(select * from sysobjects where name='tr_grade_insert') drop trigger tr_grade_insert go create trigger tr_grade_insert on grade instead of insert ---为grade表创建名称为tr_grade_insert的触发器,在执行insert操作之后触发 as declare @cnt int set @cnt = (select count(*) from student) select * ,@cnt from student select * from grade go insert into grade values('aaaaaaaaaaaa') go ---触 发器的两个临时表: --inserted: 操作之后的新表:所有新表与原始的物理表没有关系,只与当前操作的数据有关 --deleted:操作之前的旧表:所有新表与原始的物理表没有关系,只与当前操作的数据有关 if exists(select * from sysobjects where name='tr_grade_insert') drop trigger tr_grade_insert go create trigger tr_grade_insert on grade after insert as print '操作之前的表:操作之前,这一条记录还没有插入,所以没有数据' select * from deleted print '操作之后的表:已经成功插入一条记录,所有新表中有一条记录' select * from inserted go --测试: insert into grade values('aaaaa') if exists(select * from sysobjects where name='tr_grade_update') drop trigger tr_grade_update go create trigger tr_grade_update on grade after update as print '操作之前的表:存储与这个修改操作相关的没有被修改之前的记录' select * from deleted print '操作之后的表:存储这个操作相关的被修改之后 记录' select * from inserted go --测试 update grade set classname=classname+'aa' where ClassId>15 if exists(select * from sysobjects where name='tr_grade_delete') drop trigger tr_grade_delete go create trigger tr_grade_delete on grade after delete as print '操作之前的表:存储与这个修改操作相关的没有被删除之前的记录' select * from deleted print '操作之后的表:存储这个操作相关的被删除之后 记录--没有记录' select * from inserted go --测试 delete from grade where ClassId>15
存储过程就相当于c#中的方法
参数,返回值,参数默认值,参数:值的方式调用
在调用的时候有三个对应:类型对应,数量对应,顺序对应
创建语法:
create proc usp_用户自定义名称
对应方法的形参 –(int age, out string name)
as
对应方法体:创建变量,逻辑语句,增加删除修改和查询..return返回值
go
调用语法:
exec 存储过程名称 实参,实参,实参 …
--获取所有学员信息 if exists(select * from sysobjects where name='usp_getAllStuInfo') drop proc usp_getAllStuInfo go create procedure usp_getAllStuInfo as select * from Student go --调用存储过程,获取的有学员信息 execute usp_getAllStuInfo --exec sp_executesql 'select * from Student' --查询指定性别的学员信息 go if exists(select * from sysobjects where name='usp_getAllStuInfoBySex') drop proc usp_getAllStuInfoBySex go create procedure usp_getAllStuInfoBySex @sex nchar(1) --性别 参数不需要declare as select * from Student where Sex=@sex go --调用存储过程,获取指定性别的学员信息 Exec usp_getAllStuInfoBySex '女' --创建存储过程获取指定班级和性别的学员信息 go if exists(select * from sysobjects where name='usp_getAllStuInfoBySexandClassName') drop proc usp_getAllStuInfoBySexandClassName go create procedure usp_getAllStuInfoBySexandClassName @classname nvarchar(50), --班级名称 @sex nchar(1)='男'--性别 有默认的参数建议写在参数列表的最后 as declare @classid int ---班级ID set @classid=(select classid from grade where classname=@classname) --通过参数班级名称获取对应的班级ID select * from Student where Sex=@sex and ClassId=@classid go --执行存储过程获取指定班级和性别的学员信息 --exec usp_getAllStuInfoBySexandClassName '八期班' exec usp_getAllStuInfoBySexandClassName default, '八期班' --有默认值的参数可以传递default exec usp_getAllStuInfoBySexandClassName @classname='八期班' --也可以通过参数=值的方式调用 exec usp_getAllStuInfoBySexandClassName @classname='八期班' ,@sex='女' exec usp_getAllStuInfoBySexandClassName @classname='八期班',@sex='女' --创建存储过程,获取指定性别的学员人数及总人数 go if exists(select * from sysobjects where name='usp_getCountBySexandClassName') drop proc usp_getCountBySexandClassName go create procedure usp_getCountBySexandClassName @cnt int=100 output, --output标记说明它是一个输出参数。output意味着你向服务器请求这个参数的值,那么在执行的时候,服务器发现这个参数标记了output,就会将这个参数的值返回输出 @totalnum int =200output, --总人数 @className nvarchar(50), --输入参数没有默认值,在调用的时候必须传入值 @sex nchar(1)='男'--输入参数有默认值,用户可以选择是否传入值 as declare @classid int ---班级ID set @classid=(select classid from grade where classname=@classname) --通过参数班级名称获取对应的班级ID select * from Student where Sex=@sex and ClassId=@classid set @cnt= (select COUNT(*) from Student where Sex=@sex and ClassId=@classid) --获取指定班级和性别的总人数 set @totalnum=(select COUNT(*) from Student) ----获取总人数 go --调用存储过程,获取指定性别的学员人数及总人数 declare @num int,@tnum int exec usp_getCountBySexandClassName @cnt=@num output ,@totalnum=@tnum output , @className='八期班' print @num print @tnum print '做完了' ---获取指定班级的人数 if exists(select * from sysobjects where name='usp_getCount') drop proc usp_getCount go create procedure usp_getCount @className nvarchar(50)='八期班' as declare @classid int=(select classid from grade where classname=@className) declare @cnt int set @cnt =(select COUNT(*) from Student where ClassId=@classid) --return 只能返回int整数值 --return '总人数是'+cast(@cnt as varchar(2)) return @cnt go --调用存储过程,接收存储过程的返回值 declare @count int --set @count=(exec usp_getCount) exec @count=usp_getCount '八期班' print @count if exists(select * from sysobjects where name='usp_getClassList') drop proc usp_getClassList go create procedure usp_getClassList as select classid,classname from grade go
if exists(select * from sysobjects where name='usp_getPageData') drop proc usp_getPageData go create procedure usp_getPageData @totalPage int output,--总页数 @pageIndex int =1 ,--当前页码,默认是第一页 @pageCount int =5 --每一页显示的记录数 as select * from (select ROW_NUMBER() over(order by studentno) id,* from Student) temp where temp.id>(@pageindex-1)*@pagecount and temp.id<=(@pageindex*@pagecount) set @totalPage=CEILING((select COUNT(*) from Student)*1.0/@pageCount) go
select * from sysindexes --create index IX_Student_studentName --on 表名(字段名) --clustered index:聚集索引 nonclustered index--非聚集索引 if exists(select * from sysindexes where name='IX_Student_studentName') drop index student.IX_Student_studentName go create clustered index IX_Student_studentName on student(studentname) --如果是先创建主键再创建聚集索引就不可以,因为主键默认就是聚集索引 --但是如果先创建聚集索引,那么还可以再创建主键,因为主键不一定需要是聚集的
--创建局部临时表 create table #newGrade ( classid int , classname nvarchar(50) ) ---局部临时表只有在当前创建它的会话中使用,离开这个会话临时表就失效.如果关闭创建它的会话,那么临时表就会消失 insert into #newGrade select * from grade select * from #newGrade select * into #newnewnew from grade select * into newGrade from #newgrade --创建全局临时表:只要不关闭当前会话,全局临时表都可以使用,但是关闭当前会话,全局临时表也会消失 create table ##newGrade ( classid int , classname nvarchar(50) ) drop table ##newGrade select * into ##newGrade from grade select * from ##newGrade --创建表变量 declare @tb table(cid int,cname nvarchar(50)) insert into @tb select * from grade select * from @tb