课程地址:数据库 SQLServer 视频教程全集(99P)| 22 小时从入门到精通_哔哩哔哩_bilibili
目录
identity(主键自动增长,用户不需要为identity修饰的主键赋值)
用法
如何重新设置identity字段的值
如何向identity字段插入数据
视图
为什么需要视图 —— 简化查询
例子
总结
什么是视图
视图的格式
视图的优点
视图的缺点
注意的问题
事务
初学者必须要掌握的三个问题
事务是用来研究什么的
事务和线程的关系
事务和第三方插件的关系
大纲
为什么需要事务
什么是事务
如何创建事务
事务三种运行模式
自动提交事务
显式事务
隐性事务
总结事务的四大特性
原子性
一致性
隔离性
持久性
注意问题
代码示例
后期数据库内容概述
索引
存储过程
触发器
游标
TL_SQL(流程控制)
总复习
重点:数据库是如何解决数据存储问题的
查询
事务
主键通常为代理主键(无实际含义,整型数字),一般不使用有业务含义的字段充当主键
create table student2(
student_id int primary key,
student_name nvarchar(200) not null
)
insert into student2 values (1,'张三')
insert into student2 values (2,'李四')
insert into student2 values (1,'张三') -- error,主键不允许重复
insert into student2 values ('张三') -- error,主键不允许省略
insert into student2(student_name) values ('张三') -- error,把编号student_id当主键时,必须得为它赋值
identity表示该字段的值会自动更新,不需要我们维护,通常情况下我们不可以直接给 identity 修饰的字符赋值,否则编译时会报错
语法格式为:
数据类型是整型的列才能被定义成标识列
标识列通常与 primary key 约束一起用作表的唯一行标识符
例子:
create table student3(
student_id int primary key identity(100,5),
student_name nvarchar(200) not null
)
insert into student3(student_name) values ('张三') -- student_id为100
insert into student3 values ('李四') -- OK,student_id为105
select * from student3
delete from student3 where student_name = '李四'
insert into student3(student_name) values ('王五') -- student_id为110
select * from student3
总结:
如果对表中数据进行了删除操作,如何让identity字段重新从某个值开始自增?
dbcc checkident('表名', reseed, identity字段的初始值)
dbcc checkident('表名', reseed, 0)
-- 种子的值也可以是0,这样设置的话,用户插入值时,种子的初始值将从1开始
例子:
create table emp(
empid int identity(1,1),
ename nvarchar(20) not null
)
insert into emp values ('aaaa')
insert into emp values ('bbbb')
insert into emp values ('cccc')
insert into emp values ('dddd') -- 9行
select * from emp
delete from emp where empid = 4 -- 删除empid为4的记录
select * from emp
insert into emp values ('eeee') -- 因为执行9行时empid为4,所以执行本语句时empid为5
select * from emp
delete from emp where empid = 5
dbcc checkident('emp',reseed,3) -- 20行(把emp表中identity字段的初始值重新设置为3)
insert into emp values ('eeee') -- 此时插入记录时,empid为4,因为20行代码已经把empid设置成了3
select * from emp
通常identity标记的字段,我们是不需要插入数据的,即我们不需要维护identity字段的值,它会自动更新。如果我们需要向identity修饰的字段插入值,则必须满足如下两点:
set identity_insert [database.[owner.]] {table} {on|off}
create database Example
use Example
create table dept(
deptid decimal(6,0) identity,
deptname varchar(20)
)
set identity_insert Example.dbo.dept on
-- 执行本语句的目的是:希望可以向identity修饰的字段插入值
-- 不可以改为 set identity_insert dept on
-- 不可以改为 set identity_insert dbo.Example.dept on
-- 不可以改为 set identity_insert dbo.Example.dept.on
insert into dept(deptid, deptname) values (1,'zhangsan')
-- 不能改为 insert into dept values (1,'zhangsan')
select * from dept
求出平均工资最高的部门的编号和部门的平均工资
top 只有 SQL Server 里才有,MySQL和Oracle里没有这种用法
select deptno, avg(sal) "avg_sal" from emp
group by deptno -- 临时表
写法1:
select * from (
select deptno, avg(sal) "avg_sal" from emp
group by deptno -- 临时表
) T
where T.avg_sal = (
select max(E.avg_sal) from (select deptno, avg(sal) "avg_sal" from emp group by deptno) E -- 临时表
)
写法2:创建视图
create view v$_emp_1
as
select deptno, avg(sal) "avg_sal"
from emp
group by deptno -- 临时表
select * from v$_emp_1 -- 视图可以当做一个临时表
select * from v$_emp_1
where avg_sal = (select max(avg_sal) from v$_emp_1)
方便简化查询,避免了代码的冗余,避免书写大量重复的SQL语句
create view 视图的名字
as
-- select前面不能添加begin
select语句
-- select后面不能添加end
如隐藏emp表的工作年份和工资两列
create view v$_emp_2
as
select empno, ename, job, mgr, comm, deptno
from emp
select * from v$_emp_2
-- error
create view v$_a
as
select avg(sal) from emp
-- ok
create view v$_a
as
select avg(sal) as "avg_sal" from emp
不使用分组,但使用了聚合函数时,默认把所有记录当做一组
悲观锁、乐观锁...
谁访问谁上锁,会导致其他用户不能访问
脏读、串行化...
事务主要用来保证数据的合理性和并发处理的能力。通俗点说:
例子:
一系列操作要么全都执行成功,要么全部执行失败,这就是事务
T-SQL使用下列语句来管理事务:
一旦事务提交或回滚,则事务结束
默认任何一个语句就是一个事务,必须显式地开启一个事务后才能提交或回滚
执行之前开启,执行之后结束(默认)
Oracle有的语句一写完就提交,有的不是;而SQL Server都是一写完就提交
判断某条语句执行是否出错:
SET @errorSum = @errorSum + @@error
-- @ 用户变量
-- @@ 系统变量
每条单独的语句都是一个事务。如果成功执行,则自动提交;如果错误,则自动回滚(默认模式)
每个事务均以 begin transaction 语句显式开始,以 commit 或 rollback 语句显式结束
在前一个事务完成时,新事务隐式启动,但每个事务仍以 commit 或 rollback 语句结束
事务必须具备以下四个属性,简称ACID属性
事务是一个完整的操作。事务的各步操作是不可分的(原子的),要么都执行,要么都不执行
当事务完成时,数据必须处于一致状态,要么处于开始状态,要么处于结束状态,不允许出现中间状态
指当前的事务与其他未完成的事务是隔离的。在不同的隔离级别下,事务的读取操作,可以得到的结果是不同的
事务完成后,它对数据库的修改被永久保持,事务日志能够保持事务的永久性
delete from dept2 where deptno = 50
commit -- error
rollback -- error
create table bank(
customerEname nvarchar(200),
currentMoney money
)
insert into bank values ('张三',1000)
insert into bank values ('李四',1)
alter table bank add constraint check_currentMoney check(currentMoney >= 1)
select * from bank
-- 张三要给李四转账1000元
-- 则张三账户余额为1000-1000=0 < 1(不符合要求)
-- 李四账户余额为1+1000=1001
-- 理应转账失败
没有事务时:
update bank set currentMoney = currentMoney-1000 where customerEname = '张三'
update bank set currentMoney = currentMoney+1000 where customerEname = '李四'
这显然不合理
有事务时:
begin transaction
declare @errorSum int
set @errorSum = 0
update bank set currentMoney = currentMoney-1000 where customerEname = '张三'
set @errorSum = @errorSum + @@ERROR
update bank set currentMoney = currentMoney+1000 where customerEname = '李四'
set @errorSum = @errorSum + @@ERROR
if (@errorSum<>0)
begin
print '转账失败'
rollback transaction
end
else
begin
print '转账成功'
commit transaction
end
类似字典的目录,可以加快查询速度(视图只能简化查询,不能加快查询速度)。但若索引建立的不合理,反而会降低查询的速度
当对一个表执行增删改查操作时,会自动触发另外一些语句的执行(主要是为了完成一些约束功能)
对处理结果集分情况处理,对多行数据按单行方式做操作
数据库语言(第四代语言,命令,不需要考虑内部实现,但由于无for循环或if语句,功能弱)
TL_SQL是一个含有流程控制,只能用在SQL Server中的编程语言
字段、表、记录、属性、列、元素、约束、关系、主键、外键、check、default、unique、not null、触发器
distinct、内连接、视图...