SQL Server笔记(超详细,值得收藏)

个人网站: 【紫陌】【笔记分享网】
想寻找共同学习交流、共同成长的伙伴, 请点击【前端学习交流群】

目录

 

1.创建数据库

2.创建,删除表和使用表

2.1介绍表

2.2创建表

2.3删除表

2.2.1 SQL server中的数据类型

2.3更新表

2.3.1添加列(字段)

2.3.2删除列(字段)

2.4查询表

2.4.1查询单个字段

2.4.2查询多个字段

2.4.3查询整个表

2.4.5查询排序数据【order by】

2.5.6过滤数据【where】

2.5.7数据处理函数

2.5.8分组查询

2.5.9使用子查询

2.5连接查询

2.5.1 内连接之非等值连接

2.5.2内连接之非等值连接

2.5.3内连接之自连接

2.5.4外连接(右外连接)

2.5.5外连接(左外连接)

2.5.6 union合并查询结果集

2.6 top(类似mysql的limit)

2.7表的查询学完了(总结)

2.8插入数据insert

2.9修改update

2.10删除数据 delete

2.11表复制

3.视图(view)

4.约束(constraint)

1.约束的作用?

2.约束包括哪些?

1.非空约束 not null

2.唯一性约束:unique

3.主键约束(primary key,简称PK)

4.外键约束 foreign key 简称 fk(重点)

5.检查约束(CHECK)

6.默认约束(DEFAULT )

5.事务(重点)

5.1认识事务

5.2事务的实现

5.3怎么提交事务,怎么回滚事务?

5.4事务的4个特性

6.索引

6.1索引的实现原理

6.2创建和删除索引

6.3索引的失效

7.0 数据库三范式                


1.创建数据库

create datatbase 数据库名称

2.创建,删除表和使用表

2.1介绍表

数据库最基本的单元是表:table

什么是表table?为什么用表来存储数据呢?

	姓名	性别	年龄(列:字段) 
	---------------------------
	张三	男			20            ------->行(记录)
	李四	女			21            ------->行(记录)
	王五	男			22            ------->行(记录)

数据库当中是以表格的形式表示数据的。
因为表比较直观。

任何一张表都有行和列:
	行(row):被称为数据/记录。
	列(column):被称为字段。

姓名字段、性别字段、年龄字段。

了解一下:
	每一个字段都有:字段名、数据类型、约束等属性。
	字段名可以理解,是一个普通的名字,见名知意就行。
	数据类型:字符串,数字,日期等,后期讲。

	约束:约束也有很多,其中一个叫做唯一性约束,
		这种约束添加之后,该字段中的数据不能重复。

2.2创建表

# 语法
   create table table_name(
    字段名称1 字段类型 [default 默认值] [not null],--非空存在默认值 
    字段名称2 字段类型 [primary key],--主键
    字段名称3 字段类型 [foreign key references table_name(字段名称)],--外键
    字段名称4 字段类型 check(限制条件)--设置有约束
)

表名:建议以t_ 或者 tbl_开始,可读性强。见名知意。
字段名:见名知意。
表名和字段名都属于标识符。
 
代码示例:

    创建一个学生表?

	create table 学生表(
        学号 nchar(5) primary key,
        性别 nchar(1) check(性别='男' or 性别='女'),
        班级号 ncahr(3) foreign key references 班级表(班级号),
        爱好 nvarchar(100) default '无'
    )
 

注意:
        1、在同一张表中,字段名不能相同
        2、宽度 和 约束条件为可选参数,字段名 和 字段名下记录的类型 是必须的
        3、最后一个字段后不能加逗号

2.3删除表

drop table 学生表

2.2.1 SQL server中的数据类型

很多数据类型,我们只需要掌握一些常见的数据类型即可。

1.字符型:

    varchar(8000)
        可变长度的字符串
        比较智能,节省空间。
        会根据实际的数据长度动态分配空间。

        优点:节省空间
        缺点:需要动态分配空间,速度慢。

    char(8000)
        定长字符串
        不管实际的数据长度是多少。
        分配固定长度的空间去存储数据。
        使用不恰当的时候,可能会导致空间的浪费。

        优点:不需要动态分配空间,速度快。
        缺点:使用不当可能会导致空间的浪费。

        varchar和char我们应该怎么选择?
            性别字段你选什么?因为性别是固定长度的字符串,所以选择char。
            姓名字段你选什么?每一个人的名字长度不同,所以选择varchar。

    text        可变长度字符串  2GB

          nchar(n)           40000
          nvarchar(n)          4000   2字节
          nvarchar(max)           varchar长度1/2
          ntext

注意:前面带n,存储中文汉字还是英文或数字,长度都是1,存储大小2个字节,不带n,英文或数字,就是1个长度,中文就是两个长度

        unicode        字符串

2.日期型

        datetime                    精确度高,

        datetime2                  精度更高,100纳秒
          
        smalldatetime          精度1分钟  时间范围小

        date                           存储日期
           
        time                           存储时间

 

3.其他类型

  uniqueidentifier  guid  全球唯一标识符。

2.3更新表

2.3.1添加列(字段)

语法:
alter table table_name add  列名 字段类型

示例:

alter table 表名 add 列名 nchar(30);

注意:

        在实际的开发中,需求一旦确定之后,表一旦设计好之后,很少的
进行表结构的修改。因为开发进行中的时候,修改表结构,成本比较高。
修改表的结构,对应的java代码就需要进行大量的修改。成本是比较高的。
这个责任应该由设计人员来承担!

2.3.2删除列(字段)

语法:
alter table table_name
drop column 字段名

示例:
alter table 学生表
drop column 学号

2.4查询表

2.4.1查询单个字段

语法:
select 字段名 from table_name
示例:
select 姓名 from 员工表

2.4.2查询多个字段

语法:

select 字段名1,字段名2 from table_name

示例:

select 姓名,性别 from 员工表

2.4.3查询整个表

语法:
select * from table_name
示例:
select * from 员工表

这种方式的缺点:
            1、效率低
            2、可读性差。
                        在实际开发中不建议,可以自己玩没问题。

2.4.4把查询结果去除重复记录【distinct】

语法:
select distinct 字段名 from table_name
示例:
select distinct 性别 from 员工表

注意:原表数据不会被修改,只是查询结果去重。

2.4.5查询排序数据【order by】

        按一个字段排序

语法:
select 字段名 from table_name order by 字段名
示例:
select 身高 from 学生表 order by 身高

        按多个字段排序

语法:
select 字段名1,字段名2 from table_name order by 字段名1,字段名2
示例:
select 字段名1,字段名2 from 学生表 order by 字段名1,字段名2

        指定排序方向

语法:
--升序排列
select 字段名 from table_name order by 字段名 asc

--降序排列
select 字段名 from table_name order by 字段名 desc
示例:
--升序排列
select 身高 from 学生表 order by 身高 asc

--降序排列
select 身高 from 学生表 order by 身高 desc

2.5.6过滤数据【where】

        使用where语句

语法:
select 字段名1,字段名2 from table_name where 限制条件
示例:
select *from 学生表 where 性别 = '男'

        不匹配检查

语法:
select 字段名1,字段名2 from 学生表 where 字段名 <> 某个值

示例:
 列出不是团员的所有学生信息
select *from 学生表 where 党员 <> 1

注意:!= 和 <> 通常可以互换,但是并不是所有的DBMS都支持这两种不等于操作符

示例:
 列出不是团员的所有学生信息
select *from 学生表 where 团员 <> 1

        范围值检查

在where子句中使用between…and…between匹配范围中所有的值,包括指定的开始值和结束值

示例:
查找身高在1.60~1.70之间的学生信息
select *from 学生表 where 身高 between 1.50 and 1.80

        空值检查

语法:
当一个列不包含值时,称其包含空值NULL
示例:
使用select语句的is null子句来检查空值

select *from 学生表 where 性别 is null

        组合where语句

                (and操作符)

语法:
要通过不止一个列进行过滤,可以使用and操作符给where子句附加条件
示例:
select *from 学生表 where 性别 = '男'  and 团员 = 1

                 or操作符

语法:
or操作符与and操作符正好相反,它指示检索匹配任一条件的行。
示例:
select *from 学生表 where 性别 = '男'  or 团员 = 1

求值顺序

where子句可以包含任意数目的and和or操作符。允许两者结合以进行复杂、高级的过滤。

示例:
select *from 学生表 where (性别 = '女'  or 团员 = 1) and 身高 > 1.70

注意:SQL在处理or操作符前,优先处理and操作符,即and在求值过程中优先级更高。

        in操作符

语法:
        in操作符用来指定条件范围,范围中的每个条件都可以进行匹配
        in取一组由逗号分隔、括在圆括号中的合法值。


示例:
select *from 学生表 where 身高 in ('1.60','1.55','1.75')

        not 操作符

语法:
        where子句的not操作符有且只有一个功能,否定器后所跟的任何条件
        not关键字可以用在要过滤的列前,而不是列后。


示例:
select *from 学生表 where not 团员 = 1

        like关键字

称为模糊查询,支持%或下划线匹配
    %匹配任意多个字符
    下划线:任意一个字符。
    (%是一个特殊的符号,_ 也是一个特殊符号)

​
找出名字中含有A的

select 字段名 from 表名 where 字段名 like '%A%';

找出名字以T结尾的

select 字段名 from 表名 where 字段名 like '%T';

找出名字以G开始的

select 字段名 from 表名 where 字段名 like 'G%';

找出第二个字每是C的?

select 字段名 from 表名 where 字段名 like '_C%';


​

2.5.7数据处理函数

数据处理函数又被称为单行处理函数

单行处理函数的特点:一个输入对应一个输出。

和单行处理函数相对的是:多行处理函数。(多行处理函数特点:多个输入,对应1个输出!)

        常用的文本处理函数:

函数

说明

left()

返回字符串左边的字符

length()

返回字符串长度

lower()

将字符串转换为小写

ltrim()

去掉字符串左边的空格

right()

返回字符串右边的字符

rtrim()

去掉字符串右边的空格

soundex()

返回字符串的soundex值

substr() 或substring()

提取字符串的组成部分

upper()

将字符串转换为大写

        分组函数(多行处理函数)

       多行处理函数的特点:输入多行,最终输出一行。

注意:
    分组函数在使用的时候必须先进行分组,然后才能用。
    如果你没有对数据进行分组,整张表默认为一组。

函数

说明

avg()

返回某列的平均值

count()

返回某列的行数

max()

范恢复某列的最大值

min()

返回某列的最小值

sum()

返回某列之和

AVG()函数

AVG()通过对表中行数计数并计算其列值之和,求得该列的平均值。

AVG()可以用来返回所有列的平均值,也可以用来返回特定列或行的平均值。

示例:
求出成绩表中的平均成绩:
select AVG(成绩) as 平均成绩 from 成绩表

COUNT()

COUNT()函数进行计数
示例:
求出学生表中的总人数

select COUNT(*) as 总人数 from 学生表

注意:

1.使用COUNT(*)对表中的数据数目进行计数,不管表列中包含的是空值(NULL)还是非空值

2.使用COUNT(column)对特定列中具有值得行进行计数,忽略NULL值

组合分组函数

select语句可以根据需要包含多个分组函数

示例:
select COUNT(*) as 商品数目
		MIN(价格) as 最低商品价格
		MAX(价格) as 最高商品价格
		AVG(价格) as 商品均价
from 商品表

2.5.8分组查询

分组:

是使用select语句的group by子句建立的

求出每种商品的商品数量

select 商品名,COUNT(*) as 商品数量
from 商品表
group by 商品名

重点结论:

  1. group by子句可以包含任意数目的列
  2. 如果group by 子句中嵌套了分组,数据将在最后指定的分组上进行汇总。
  3. group by 子句中列出的每一列都必须是检索列或者有效的表达式
  4. 大多数SQL实现不允许group by列带有长度可变得数据类型
  5. 除聚集计算语句外,select 语句中的每一列都必须在group by子句中给出
  6. 如果分组列中包含具有NULL值得行,则NULL将作为一个分组返回,如果列中有多行NULL,他们将会分为一组
  7. group by子句必须出现在where子句之后 order by 子句之前。

过滤分组(having)

where过滤行,having过滤分组

having支持所有where操作符

示例:

示例:
求出商品数量大于等于2的商品数量

select 商品名,COUNT(*) as 商品数量
from 商品表
group by 商品名
having COUNT(*)>=2

where在数据分组前进行过滤,having在数据分组后进行过滤

2.5.9使用子查询

子查询:

select语句中嵌套select语句,被嵌套的select语句称为子查询。

利用子查询进行过滤

在select 中子查询总是从内向外进行处理,作为子查询的select语句只能查询单个列

示例:
select
		..(select).
	from
		..(select).
	where
		..(select)


select * from 选课表 where 学号 in 
(select 学号 from 学生表 where 性别 = '男')

2.5连接查询

什么是连接查询?

从一张表中单独查询,称为单表查询。 emp表和dept表联合起来查询数据,从emp表中取员工名字,从dept表中取部门名字。 这种跨表查询,多张表联合起来查询数据,被称为连接查询。

根据表连接的方式分类:
    内连接:
        等值连接
        非等值连接
        自连接

    外连接:
        左外连接(左连接)
        右外连接(右连接)

    全连接

当两张表进行连接查询时,没有任何条件的限制会发生什么现象?

当两张表进行连接查询,没有任何条件限制的时候,最终查询结果条数,是两张表条数的乘积,这种现象被称为:笛卡尔积现象。(笛卡尔发现的,这是一个数学现象。)

怎么避免笛卡尔积现象?

连接时加条件,满足这个条件的记录被筛选出来!

语法:
select 员工表的员工名字,部门表的部门名
from 员工表,部门表
where 员工表.名字=部门表.部门名

示例:
select 
	emp.ename,dept.dname 
from 
	emp, dept
where
	emp.deptno = dept.deptno;

注意:通过笛卡尔积现象得出,表的连接次数越多效率越低,尽量避免表的连接次数

2.5.1 内连接之非等值连接

--inner可以省略(带着inner可读性更好!!!一眼就能看出来是内连接)
select 
	e.ename,d.dname
from
	emp e    -- as省略了,给字段起别名,效率更高
inner join
	dept d
on
	e.deptno = d.deptno; -- 条件是等量关系,所以被称为等值连接。

2.5.2内连接之非等值连接

案例:找出每个员工的薪资等级,要求显示员工名、薪资、薪资等级?

select 
	e.ename, e.sal, s.grade
from
	emp e
join
	salgrade s
on
	e.sal between s.losal and s.hisal; // 条件不是一个等量关系,称为非等值连接。

2.5.3内连接之自连接

案例:查询员工的上级领导,要求显示员工名和对应的领导名?

emp a 员工表               emp b 领导表

select 
	a.ename as '员工名', b.ename as '领导名'
from
	emp a
join
	emp b
on
	a.mgr = b.empno; --员工的领导编号 = 领导的员工编号

以上就是内连接中的:自连接,技巧:一张表看做两张表

注意:

内连接:(A和B连接,AB两张表没有主次关系。平等的。)

2.5.4外连接(右外连接)

语法:
select 员工表.员工名,部门表.部门名 
from 员工表 right join 部门表 on 员工表.编号=部门表.编号

语法
-- outer是可以省略的,带着可读性强。
select 
	e.ename,d.dname
from
	emp e 
right outer join 
	dept d
on
	e.deptno = d.deptno;

right代表什么:表示将join关键字右边的这张表看成主表,主要是为了将 这张表的数据全部查询出来,捎带着关联查询左边的表。 在外连接当中,两张表连接,产生了主次关系。

2.5.5外连接(左外连接)

语法:
select 员工表.员工名,部门表.部门名 
from 部门表 right join 员工表 on 员工表.编号=部门表.编号


-- outer是可以省略的,带着可读性强。
select 
	e.ename,d.dname
from
	dept d 
left outer join 
	emp e
on
	e.deptno = d.deptno;

带有right的是右外连接,又叫做右连接。

带有left的是左外连接,又叫做左连接。

任何一个右连接都有左连接的写法。

任何一个左连接都有右连接的写法。

三张表,四张表怎么连接?

语法:
		select 
			...
		from
			a
		join
			b
		on
			a和b的连接条件
		join
			c
		on
			a和c的连接条件
		right join
			d
		on
			a和d的连接条件

2.5.6 union合并查询结果集

语法;
select 字段名1,字段名2,字段名3
from table_name
where 限制条件1
union
select 字段名1,字段名2,字段名3
from table_name
where 限制条件2

示例:
select 姓名,性别
from 学生表
where 学号 in ('01','02','03')
union
select 姓名,性别
from 学生表
where 学号 ='04'

注意:union的效率要高一些。对于表连接来说,每连接一次新表,则匹配的次数满足笛卡尔积,成倍的翻。但是union可以减少匹配的次数。在减少匹配次数的情况下,还可以完成两个结果集的拼接。

2.6 top

在SQL Server中,不支持 Limit 语句。

解决方案:
虽然SQL Server不支持 Limit ,但是它支持 TOP。

案例:

要查询前6条记录

select top 6 字段 from 表名

要查询第 3 条到第 10 条记录

select top 8 id from 表名
where 字段名1 not in (
select top 2 字段名1 from 表名
)

取第m条到第n条记录:

select top (n-m+1) id from tablename
where id not in (
select top m-1 id from tablename
)

按照薪资降序,取出排名在前5名的员工

select 
	ename,sal
from
	emp
order by 
	sal desc
limit 5; --取前5

缺省用法:limit 5; 这是取前5.

注意:mysql当中limit在order by之后执行

取出工资排名在[3-5]名的员工?

select 
		ename,sal
	from
		emp
	order by
		sal desc
	limit
		2, 3;

2.7表的查询学完了(总结)

select 
		...
	from
		...
	where
		...
	group by
		...
	having
		...
	order by
		...
	limit
		...


以上关键字只能按照这个顺序来,不能颠倒。

执行顺序?
	1.from
	2.where
	3.group by
	4.having
	5.select
	6.order by
	7.limit..

从某张表中查询数据,
先经过where条件筛选出有价值的数据。
对这些有价值的数据进行分组。
分组之后可以使用having继续筛选。
select查询出来。
最后排序输出!

2.8插入数据insert

语法格式:
	insert into 表名(字段名1,字段名2,字段名3...) values(值1,值2,值3);

insert语句中的“字段名”可以省略

注意:前面的字段名省略的话,等于都写上了!所以值也要都写上!

语法:
insert into table_name 
values(值1, 值2,....)

示例:
insert into 学生表01
values('李明','男','1.70')

2.9修改update

语法:
update table_name
set
字段名1='值',
字段名2='值'
where 限制条件

示例:
update 学生表
set
姓名='小红',
性别='女'
where 学号='01'

注意:没有条件限制会导致所有数据全部更新。

2.10删除数据 delete

语法;
delete from table_name
where 要删除行的信息

示例:
delete from 学生表
where 学号='01'

快速删除表中的数据?【truncate比较重要,必须掌握】
 

--删除dept_bak表中的数据
delete from dept_bak; --这种删除数据的方式比较慢。

用法:truncate table dept_bak; (这种操作属于DDL操作。)

删除表操作?
	drop table 表名; -- 这不是删除表中的数据,这是把表删除。

delete语句删除数据的原理?(delete属于DML语句!!!)
    表中的数据被删除了,但是这个数据在硬盘上的真实存储空间不会被释放!!!
    这种删除缺点是:删除效率比较低。
    这种删除优点是:支持回滚,后悔了可以再恢复数据!!!

truncate语句删除数据的原理?
    这种删除效率比较高,表被一次截断,物理删除。
    这种删除缺点:不支持回滚。
    这种删除优点:快速。

大表非常大,上亿条记录?
    删除的时候,使用delete,也许需要执行1个小时才能删除完!效率较低。
    可以选择使用truncate删除表中的数据。只需要不到1秒钟的时间就删除结束。效率较高。
    但是使用truncate之前,必须仔细询问客户是否真的要删除,并警告删除之后不可恢复!

    truncate是删除表中的数据,表还在!

2.11表复制

create table dept2 as select * from dept;

3.视图(view)

什么是视图?

view:站在不同的角度去看待同一份数据。

数据库中的建立的表table叫物理表

view是查询结果的保存,它是虚拟表

怎么创建视图对象?

语法:

create view table_name as
select 创建视图的相应信息

示例:

create view 学生成绩表 as
select 学生表.学号,课程名称,成绩
from 学生表,成绩表,课程表
where 学生表.学号 = 成绩表.学号
and 成绩表.课程编号 = 课程表.课程编号

用视图做什么?

我们可以面向视图对象进行增删改查,对视图对象的增删改查,会导致原表被操作!(视图的特点:通过对视图的操作,会影响到原表数据。)

视图对象在实际开发中到底有什么用?

《方便,简化开发,利于维护》

假设有一条非常复杂的SQL语句,而这条SQL语句需要在不同的位置上反复使用。
    每一次使用这个sql语句的时候都需要重新编写,很长,很麻烦,怎么办?
        可以把这条复杂的SQL语句以视图对象的形式新建。
        在需要编写这条SQL语句的位置直接使用视图对象,可以大大简化开发。
        并且利于后期的维护,因为修改的时候也只需要修改一个位置就行,只需要
        修改视图对象所映射的SQL语句。
    
    我们以后面向视图开发的时候,使用视图的时候可以像使用table一样。
    可以对视图进行增删改查等操作。视图不是在内存当中,视图对象也是
    存储在硬盘上的,不会消失。

    再提醒一下:
        视图对应的语句只能是DQL语句。
        但是视图对象创建完成之后,可以对视图进行增删改查等操作。

4.约束(constraint)

1.约束的作用?

在创建表时我们需要给表中的字段增加一些约束,来保证表数据的完整性,有效性

2.约束包括哪些?

  1. 非空约束 not null
  2. 唯一性约束  unique
  3. 主键约束  primary key(简称pk)
  4. 外键约束  foreign key (简称fk)
  5. 5.检查约束(CHECK)
  6. 默认约束(DEFAULT )

1.非空约束 not null

非空约束所约束的字段不能为null。

ALTER TABLE 数据表名称
ALTER COLUMN ID INT NOT NULL

2.唯一性约束:unique

唯一性约束unique约束的字段不能重复,但是可以为NULL。

ALTER TABLE 数据表名称
ADD CONSTRAINT QU_Name		--(命名一个唯一约束的名称)
UNIQUE([Name])

3.主键约束(primary key,简称PK)

主键约束的相关术语:主键约束、主键字段、主键值。
主键值是每一行记录的唯一标识。

注意:任何一张表都应该有主键,没有主键,表无效!

主键的特征:not null + unique(不能为空,同时不能重复)

添加主键约束:

ALTER TABLE 数据表名
ADD CONSTRAINT PK_ID		--(命名一个主键名称)
PRIMARY KEY(ID)

4.外键约束 foreign key 简称 fk(重点)

当两张表有父子关系时,子表上与父表关联的字段为保证数据有效需要加外键约束,被引用的字段可以不是主键可以为null但是必须具有唯一性

ALTER TABLE 从表名称
ADD CONSTRAINT FK_SID		--(命名一个外键名称)
--添加外键约束
FOREIGN KEY(StuID) REFERENCES 主表名称(ID)

5.检查约束(CHECK)

设置这个字段中的数据特性

ALTER TABLE 数据表名称
ADD CONSTRAINT CK_SEX				--(命名一个检查约束的名称)
CHECK(SEX IN('男','女'));

6.默认约束(DEFAULT )

若在表中定义了默认值约束,用户在插入新的数据行时,如果该行没有指定数据,那么系统将默认值赋给该列,如果我们不设置默认值,系统默认为NULL。

1. 如果表字段已经建好

--DF_XXX(命名一个默认约束的名称)
ALTER TABLE 表名 
ADD CONSTRAINT DF_XXX  DEFAULT 1 FOR 字段名

 2.如果表字段没有建

ALTER 表名 ADD 字段名 INT DEFAULT(1)

删除约束

--删除检查约束
ALTER TABLE 数据表名称
DROP CONSTRAINT CK_AGE				--(你想要删除的某个键名或者约束名称)

5.事务(重点)

5.1认识事务


一个事务其实就是一个完整的业务逻辑,是一个最小的工作单元。要么同时成功,要么同时失败,不可再分。

假设转账,从A账户向B账户转账10000
A账户的钱减去10000(update语句)
B账户的钱加上10000(update语句)
这就是一个完整的业务逻辑

这两个update语句要求必须同时成功或者同时失败,才能保证钱是正确的。

只有DML语句才会有事务这一说,其他语句和事务无关。
insert、delete、update。
一旦你的操作涉及到增、删、改,那么就一定要考虑安全问题。

5.2事务的实现

事务:就是批量的DML语句同时成功,或者同时失败。

事务是怎么做到多条DML语句同时成功和同时失败的?
InnoDB存储引擎:提供一组用来记录事务性活动的日志文件。

事务开启:
insert
delete
update

事务结束

在事务执行过程中。每一条DML的操作都会记录到“事务性活日志文”中

在事务执行过程中我们可以提交事务也可以回滚事务

提交事务:清空事务性活动的日志文件,将数据全部彻底持久化到数据库表中,标志着事物成功结束

回滚事务:清空事务性活动的日志文件,将所有的DML操作全部撤销,标志着事务失败结束

5.3怎么提交事务,怎么回滚事务?

提交事务:commit

回滚事务:rollback

mysql默认情况下自动提交事务,那怎么自己提交事务呢?

START TRANSACTION;

SELECT * FROM dept;
START TRANSACTION;
INSERT INTO dept VALUE(50,'jjj','yyyy');
SELECT * FROM dept;
ROLLBACK;
SELECT * FROM dept;

事务一旦提交回滚就没有作用

SELECT * FROM dept;
START TRANSACTION;
INSERT INTO dept VALUE(50,'jjj','yyyy');
SELECT * FROM dept;
COMMIT;
ROLLBACK;
SELECT * FROM dept;

5.4事务的4个特性

ACID

  • 原子性(A):说明事务是最小的工作单元,不可再分。
  • 一致性(C):所有事务要求,在同一个事务当中,所有操作必须同时成功,或者同时失败,以保证数据的一致性。
  • 隔离性(I):A事务和B事务之间具有一定的隔离。相当于多线程并发访问的每个线程。
  • 持久性(D):事务最终结束的一个保障。事务提交,就相当于将没有保存到硬盘上的数据保存到硬盘上!

事务与事务之间有4个隔离级别

  • 读未提交:read uncommitted(最低隔离级别)
    事务A可以读取到事务B未提交的数据。(没有提交就读取到了)
    这种隔离级别存在的问题就是:脏读现象(Dirty Read),我们称堵到了脏数据。
    这种隔离级别一般都是理论上的,大多数的数据库隔离级别都是二挡起步。
  • 读已提交:read commited
    事务A只能读取到事务B提交之后的数据。解决了脏读现象。
    这种隔离级别存在的问题是:不可重复读取数据。
    这种隔离级别是比较真实的数据,每次读到的数据是绝对真实的。
    Oracle数据库默认的隔离级别是:read commited
  • 序列化/串行化:serializable(最高的隔离级别)
    这是最高隔离级别,效率最低。解决了所有的问题。
    这种隔离级别表示事务排队,不能并发!
    synchronized,线程同步(事务同步)
    每次读取到的数据都是最真实的,但是效率是最低的。

6.索引

索引是在数据库表的字段上添加的,是为了提高查询效率存在的一种机制。
一张表的一个字段可以添加一个索引,当然,多个字段联合起来也可以添加索引。
索引相当于一本书的目录,是为了缩小扫描范围而存在的一种机制。

根据SQL语句扫描:select * from t_user where name = 'jack',扫描name查找。
如果name字段上没有添加索引(目录),或者说没有给name字段创建索引,MySQL会进行全扫描,会将name字段上的每一个值都比对一遍。效率比较低。

MySQL在查询方面主要就是两种方式:
第一种方式:全表扫描。
第二种方式:根据索引检索。

在mysql数据库当中,索引也是需要排序的,并且这个索引的排序和TreeSet数据结构相同。TreeSet底层是一个自平衡的二叉树!在mysql当中索引是一个B-Tree数据结构。
遵循左小右大原则存放,采用中序遍历方式遍历取数据。

6.1索引的实现原理

SQL Server笔记(超详细,值得收藏)_第1张图片

什么情况下,我们会考虑给字段添加索引呢?
1.数据量庞大(到底有多么庞大算庞大,这个需要测试,因为每一个硬件环境不同)。
2.该字段经常出现在where的后面,以条件的形式存在,也就是说这个字段总是被扫描。
3.该字段很少的DML操作,因为DML之后,索引需要重新排序。

建议不要随意添加索引,因为索引也是需要维护的,太多的话反而会降低系统的性能。建议通过主键查询,建议通过unique约束的字段进行查询,效率会比较高。

6.2创建和删除索引

创建索引:
create index emp_ename_index on emp(ename);
给emp表的ename字段添加索引,起别名:emp_ename_index

删除索引:
drop index emp_ename_index on emp;
将emp表上的emp_ename_index索引对象删除。

在mysql当中,查看一个SQL语句是否使用了索引进行检索:
explain select * from emp where ename = 'KING';

6.3索引的失效

索引也有失效的情况,如下:

"%"开头的模糊查询
select * from emp where ename like '%T';
尽量避免模糊查询的时候以"%"开头,这是一种优化的策略。
可以用SQL语句查看:explain select * from emp where ename like '%T';

使用or
如果使用or,那么要求or两边的条件字段都要有索引,索引才生效。如果其中一个字段没有索引,那么另一个字段上的索引也会失效。所以不建议使用or,可以使用union来代替。

使用复合索引
使用复合索引的时候,要使用左侧的列查找,索引才生效。使用右侧,则失效。
复合索引:两个字段,或者更多的字段联合起来添加一个索引。
create index emp_job_sal_index on emp(job,sal);
使用左侧:explain select * from emp where job = 'MANAGER'; 生效
使用右侧:explain select * from emp where sal= 800; 失效

索引列参与运算
在where当中索引列参加了运算,索引失效。
explain select * from emp where sal+1 = 800;

索引列使用了函数
在where当中索引列使用了函数。
explain select * from emp where lower(ename) = 'smith';

还有其他情况,先了解这些…

索引是各种数据库进行优化的重要手段,优化的时候优先考虑的因素就是索引。
索引在数据库当中分了很多类:

  1. 单一索引:一个字段上添加索引。
  2. 复合索引:两个字段或者更多的字段上添加索引。
  3. 主键索引:主键上添加索引。
  4. 唯一性索引:具有unique约束的字段上添加索引。(注意:唯一性比较弱的字段上添加索引的用处不大。)

例:需要在examination_info表创建以下索引,规则如下:
在duration列创建普通索引 idx_duration、在exam_id列创建唯一性索引 uniq_idx_exam_id、在tag列创建全文索引 full_idx_tag。

create index idx_duration on examination_info(duration);
create unique index uniq_idx_exam_id on examination_info(exam_id);
create fulltext index full_idx_tag on examination_info(tag);

7.0 数据库三范式                

数据库设计范式:数据库表的设计依据,教你怎么进行数据库表的设计。

第一范式:要求任何一张表必须有主键,每一个字段原子性不可再分。
第二范式:建立在第一范式的基础上,要求所有非主键字段完全依赖主键,不要产生部分依赖。
第三范式:建立在第二范式的基础上,要求所有非主键字段直接依赖主键,不要产生传递依赖。

三范式是面试官经常问的,一定要熟记于心!!!

设计数据表的时候,按照以上的范式进行,可以避免表中数据的冗余,空间的浪费。

总结数据库表的设计:

一对一,第二张表外键唯一(fk+unique)
一对多,两张表,多的表加外键!
多对多,三张表,关系表两个外键!

嘱咐:
数据库设计三范式是理论上的,实践和理论有的时候有偏差。
最终的目的都是为了满足客户的需求,有的时候会拿冗余换执行速度。
因为在SQL中,表和表之间连接次数越多,效率越低。(笛卡尔积)
有的时候可能会存在冗余,但是为了减少表的连接次数,这样做也是合理的,并且对于开发人员来说,SQL语句的编写难度也会降低。

你可能感兴趣的:(数据库,数据库,sql,sqlserver)