【学习笔记】数据库小结

本文详细介绍了MySQL数据库的常用命令,包括SQL语言分类、DDL、DCL、DQL和DML,以及SQL文件操作。讲解了简单查询、条件查询、排序、数据处理函数、分组查询、连接查询、子查询、事务、索引、视图和数据库设计三范式等关键概念,并提供了丰富的示例。此外,还探讨了事务的隔离性和索引的失效场景。

Msql常用命令:

本地登录:

mysql -uroot -proot

退出mysql:

exit;

showdatabase;

use xxx;

show tables;

desc xxx;

SQL语言分类

  • DML(Data Manipulation Language)数据操纵语言

如:insert,delete,update,select(插入、删除、修改、检索)简称CRUD操新增Create、查询Retrieve、修改Update、删除Delete

DDL(Data Definition Language)数据库定义语言

如:create,drop,alter之类,主要是对表结构进行操作。

DCL(Data Control Language)数据库控制语言

如:grant、deny、revoke等,只有管理员才有相应的权限

DQL(Data Query Language)数据库查询语言

如: select 语法

注意:SQL不区分大小写

sql文件相关操作:

1.导入

先use一个数据库然后

source + 直接拖进去

2.查询表中所有数据

select* from + 表名

3.不看表的数据,只看表的结构

desc + 表名

4.查看数据库版本号+使用数据库

select version();

select database();

5.\c 用来终止输入

简单查询:

查询字段(列):

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

强调:sql 以; 结尾,不区分大小写

select * from 表名 ;

效率低,可读性差,不建议开发写

给查询的列起别名:

select 字段名1,字段名2 as 别名 from 表名;(as)可以省略

注意只是将显示的查询结果显示,原表名字不会更改

如果别名里相加空格,就用单引号括起来

注意:所有数据库中,字符串统一用单引号

注:字段名 可以 + - x /

条件查询:

查询符合条件的数据:

select

字段

from

表名

where

条件

sal >=800 and sal<=3000;

sal between 800 and 3000;【】闭区间,包括两端的值

使用between and 时 必须左小右大

都有哪些条件:

= ,< ,> ,!= , <>, <=, >=,between and ,>= adn <=,

is null,is not null,

select empno,ename from emp where sal=800;

等号可以运用在字符串上

or:

select ename,job from emp where job=’manager‘ or job=’salesman‘;

and 和 or同时出现:and优先级高

select ename, job from emp where sal >2500 and deptno =10 or deptno =20;会按一下顺序执行:

select ename, job from emp where (sal >2500 and deptno =10) or deptno =20;

正确执行方式:

select ename, job from emp where sal>2500 and (deptno =20 or deptno=10);

in:相当于多个or,但不是多个区间,in后面跟的是具体的值

select empno,ename,job from emp where job in('manager' ,"salesman");

select empno,ename,job from emp where job='manager' or job="salesman";

like:模糊查询

%和_是特殊的符号,

%:任意多个字符,也可能是一个

_:任意一个字符

找出名字中含有o的:

select ename from emp where ename like '%o%';

以t结尾:

select ename from emp where ename like '%t';

以k开始:

select ename from emp where ename like 'k%';

第二个字母是a:

select ename from emp where ename like '_a%';

第三个字母是r:

select ename from emp where ename like '__r%';

找出含有_的名字:

select ename from emp where ename like '%\_%'

\转义,不然会全都查找出来

排序:

默认是升序:

select ename,sal from emp order by sal (asc);默认不写就是升序

降序:

select ename,sal from emp order by sal desc;(descend)

按照薪资升序排列,如果薪资一样,按照名字升序排列:

select ename,sal from emp order by sal,ename;

注:sal在前起主导,只有sal相等情况下才轮到ename

小综合:

select

ename,sal

from

emp

where

sal between 1250 and 3000

order by

sal desc;

数据处理函数,单行处理:

又叫单行处理函数:

特点:一个输入对应一个输出,

和单行处理函数相对的是多行处理函数:多个输入对应一个输出。

常见的单行处理函数:

lower:

select lower(ename) from emp;

upper:

select upper(ename) as ename from emp;

substr

select substr(ename,1,3) as ename from emp;

起始下标从1开始

找出名字第一个字母是a的:

第一种:模糊查找:

select ename from emp where ename like 'a%';

第二种:

select ename from emp where substr(ename,1,1) ='a';

concat:字符串拼接

select concat(substr(ename,1,1),lower(substr(ename,2,length(ename))))

from emp;

length:上面那个

trim:

select * from emp where ename = trim(' king ');

去掉前后空格

round:

select round(123.23153,3) from emp;

四舍五入保留小数位

select round(1236.23153,-1) from emp; //1240

rand:

select rand() from emp;

select round(rand()*100) from emp;

null:

null参与运算最后结果都是null

select ename,(ifnull(comm,0)+sal)*12 from emp;

case..when...then...when...then...else...end

当工作岗位是manager,工资上调10%

当工作岗位是salesman时,工资上调50%

注意:不修改数据库,只是将查询结果显示显示出来

select ename,job, (case job when 'manager' then salx1.1 when 'salsman' then sal*1.5 else sal end ) as sal from emp;

分组函数,多行处理函数:

输入多行最终输出一行

5个:

count 计数

sum 求和

avg 平均值

max 最大

min 最小

注意:分组函数必须先进行分组才能用!!!

如果没有分组,整张表默认为一组

注:分组函数自动忽略null,不需要对null提前处理。

count(*)数全部的行

count(字段)统计该字段下不为null的元素总数

分组函数不能直接使用在where中??????????????????

所有的分组函数可以组合起来一起用

分组查询*****

先进行分组,再对每一组的信息操作

select

**...**

from

...

where

...

group by

....

having

...

order by

**...**

计算每个部门的工作和?计算每个工作岗位的平均薪资?最高薪资?

执行顺序

1.from2.where3.group by4.having5.select6.order by7.limit**

先经过where筛选,再分组,然后having过滤,再挑选,再排序

为什么分组函数不能使用在where后面?

以为分组函数在使用的时候要先分组,where执行时还没分组,所以where后面不能出现分组函数

重点结论:

在一条select语句中,如果有group by 语句,select后面只能跟:参加分组的字段,以及分组的函数,其他一律不能跟

找出每个部门的最高薪资:

这样写没有意义,select后面加加ename无意义。

找出每个部门不同岗位的最高薪资:

*having:

先将》3000的都找出来然后再分组

综合案例:

找出每个岗位的平均薪资,要求显示平均薪资》1500的,除manager之外

要求按照平均薪资升序排列。

select avg(sal),job from emp where job != 'manager'group by job having avg(sal)>1500 order by avg(sal) ;

distinct

distinct 放在字段前面,联合起来判断

统计工作岗位的数量,有多少工种:

连接查询

跨表查询,多张表连一起查询

分类:

内连接:

等值连接

非等值连接

自连接

外连接:

左外连接

右外连接

全连接

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

案例:

select ename, dname from emp,dept where emp.deptno=dept.deptno order by dname;

思考:最终查询结果为14条但是匹配次数减少了吗?没有!还是14*4次,只是四选一,上面14条记录,一一跟下面的表的四条记录进行匹配。

这叫做笛卡尔积现象!!!!!

select emp.ename, dept.dname from emp,dept where emp.deptno=dept.deptno order by dname;

下面这张情况,匹配次数少了,给表起别名:

内连接之等值连接

查询每个员工所在的部门名称,显示员工名和部门名:

SQL92:缺点,表连接的条件在where里,结构不清晰

select

e.ename,d.dname

from

emp e,dept d

where

e.deptno=d.deptno;

SQL99:结构更清晰一点

select

e.ename,d.dname

from

emp e,

(inner)join

dept d

on

e.deptno=d.deptno;

优点,连接独立,可以继续添加where筛选

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

内连接之自连接

自己跟自己连接

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

一张表看成两张表

外连接:左右连接

select

e.ename,d.dname ,e.deptno ,d.deptno

from

emp e

right (outer) join

dept d

on

e.deptno=d.deptno;

right 表示把右边表的数据全部显示出来,捎带着查询左边的表

两张表产生了主次关系,右边的是主表

左右连接是想通的

外连接的查询结果条数一定>=内连接查询结果条数

案例:查询每个员工的上级领导,要求显示所有员工的名字和领导名

select e.ename as 'emp' , e1.ename as 'leader' from emp as e left join emp as e1 on e.mgr=e1.empno;

多张表的连接

select ..from a

join b on a,b的连接条件

join c on a,c的条件

join d on a,d的条件

案例:找出每个员工的部门名称,和薪资等级,(上级领导),显示员工名,薪资,部门名,薪资等级

慢慢写就行了 一点也不难

子查询

select语句中 嵌套select

子查询都可以出现在哪里?

select

...(select )...

from

....(select).....

where

.....(select)...

where子查询:

案例:找出比最低工资高的员工姓名和工资

1.找出最小的

2.找出》最小的

select ename , sal from emp where sal >(select min(sal) from emp);

from子查询

技巧:from后面的子查询可以将查询结果当作一张临时表来看待

案例:找出每个岗位的平均工资的薪资等级

1.:找出每个岗位的平均工资

2.把上面的表当做一个临时表 t,与下面的s表进行表连接

  1. 要给avg(sal)起别名

select

t.*,s.grade

from

(select job,avg(sal) as avgsal from emp group by job) as t

join

salgrade s

on

t.avgsal between s.losal and s.hisal

或者颠倒一下

select s.grade , t.avgsal from salgrade s

join

( select job,avg(sal) as avgsal from emp group by job) as t

on

t.avgsal between s.losal and s.hisal

union合并查询

查询工作岗位是manager 和 salesman的员工

1.select ename , job from emp where job='manager' or job='salesman';

2.select ename , job from emp where job in ('manager','salesman');

3.select ename , job from emp where job='manager'

union

select ename , job from emp where job='salesman';

注意:

union效率会高一点,对于表连接来说,每连接一次新表,则匹配的次数需要满足笛卡尔积,成倍的翻。。。

但是union可以减少匹配的次数,在减少匹配的次数下,还可以完成两个结果集的拼接。

a连接b连接c

a10条记录

b10条记录

c10条记录

匹配次数:1000

a连接b:100次

a连接c:100次

使用union的话,100+100=200次 等于两个查询结果拼装在一起

把乘法运算变成了加法运算

union使用的注意事项:

上下的列数要相同,列和列的数据类型也要一样,不然没法合并

limit:

将查询结果一部分显示出,通常使用在分页当中。

取前五条记录,limit:5 。limit是在order by之后执行

完整用法:limit startIndex , length; 起始下标 和 长度

不写,默认startIndex为0

取3到5名:limit 2,3 ;

分页,每页显示3条记录

第1页:limit 0,3

第2页:limit 3,3

第3页:limit 6,3

第4页:limit 9,3

每页显示pagesize条记录

第1页:limit (pagenumber-1)*pagesize,pagesize

第2页:limit (pagenumber-1)*pagesize,,pagesize

第3页:limit (pagenumber-1)*pagesize,,pagesize

第4页:limit (pagenumber-1)*pagesize,,pagesize

表的创建(DDL)

DDL: create drop alter

create table 表名(

字段名1 数据类型,

字段名2 数据类型,

字段名3 数据类型

);

表名:建议以t_或者tbl__ 开始

表名和字段名都数据标识符:要见名只意

数据类型:

varchar

可变长度字符串,会动态分配空间,比较智能,节省空间

最长255

优点:节省空间,但需要动态分配空间,速度快

char

定长字符串,不管实际数据长度多少,都会分配固定长度

最长255

缺点:使用不恰当时,会导致空间的浪费

优点:不需要动态分配空间,速度快

如何选择?性别->char,固定长度的选择char

int

就是int 最长11

bigint

等同于long

float

单精度浮点

double

双精度浮点

date

短日期类型

datetime

长日期类型

clob

字符大对象

最多可以存储4g的字符串,如存储一篇文章,存储一个简介,一个说明

character large Object

blob

二进制大对象

binary large object

专门用来存储图片、声音、视频流等媒体数据

让blob上插入视频等文件要io流

删表:

drop table if exists t_table;

插入数据insert(DML)

insert into 表名(字段名1,字段名2,字段名3.。。)

values(值1,值2,值3)[这边可以插入多条记录];

注意:字段名和值要一一对应。

insert into t_student (no,name,age,email) values (1,'zhangsan',18,'90315@qq.com');

格式化数字format

select ename,format(sal,'$999,999') as sal from emp;

str_to_date:将字符串varchar类型转换成date类型

date_format:将date类型转化为具有一定格式的varchar类型

str_to_date ('字符串日期',‘日期格式’)

str_to_date('01-12-1999','%d-%m-%Y')

mysql的日期格式

%Y 年

%m 月

%d 日

%h 时

%i 分

%s 秒

如果提供日期字符串是这个格式,可以省略str_to_date,自动类型转换

‘%Y-%m-%d’

date和datetime

mysql短日期‘%Y-%m-%d’

mysql长日期‘%Y-%m-%d %h:%i:%s’

修改update(DML)

update 表名 set 字段名1=值1 ,字段名2=值2,字段名3=值3.。。where 条件;

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

删除delete(DML)

delete from 表名 where 条件;

注意:没有条件

delete删除支持回滚 rollback回复,缺点是删除效率比较低

truncate

物理删除,不支持回滚,优点,快

增删改查

insert delete update select

快速创建表,表的复制

create table emp2 as select * from emp;

create table my_table as select ename,empno from emp where job='manager';

等于把查询结果当做一个表新建

将查询结果插入到一个表中?

insert into dept_bak select * from dept;

约束*****

constraint,创建表时给表中字段加上一些约束,保证数据的完整性,有效性。

约束的作用就是为了保证:表中的数据有效!!

约束包括:

非空约束 not null

唯一性约束 unique

主键约束 primary key

外键约束 foreign key

检查约束 check

非空约束:not null

drop table if exists t_vip;

create table t_vip(

id int,

name varchar(255) not null,

);

insert into t_vip(id,name) values(1,'zhangsan');

insert into t_vip(id,name) values(2,'lisi');

唯一性约束:unique

不能重复,但是能都为null,null可以重复

联合唯一性:一个人可以有多个邮箱,一个邮箱只能有一个主人

drop table if exists t_vip;

create table t_vip(id int,

name varchar(255) ,

email varchar(255),

unique(name,email)

);

insert into t_vip(id,name) values('zhangsan','zhangsan@qq.com');

insert into t_vip(id,name) values(zhangsan','zhangsan@163.com');

表级约束

给多个字段联合起来添加某一个约束

unique和not null联合

create table t_vip(id int,

name varchar(255) notnull unique

);

主键约束:primary key(pk)

相关术语:

主键约束:一种约束

主键字段:该字段上添加了主键约束,这样的额字段叫主键字段

主键值:主键字段中的值

主键值存在的意义就是这一行记录的身份证号,不建议使用复合主键

create table t_vip(id int,

age int primary key

);

一张表主键约束只能添加一个

主键值建议使用:

int bigint char 不建议使用 varchar做主键,主键值一般都是数字,定长的

主键出了单一,复合主键,还能如此分类:

自然主键:主键值是个自然数

业务主键:主键值跟业务关联,如;拿银行卡号当主键

实际开发,自然主键多,因为主键只意做到不重复就行 不需要有意义

业务主键不好,业务发生变动时可能会影响到主键值,所以业务主键不建议使用,尽量使用自然主键。

drop table if exists t_vip;

create table t_vip(id int primary key auto_increment, //表示自增,从1开始自增

name varchar(255) ); insert into t_vip(name) values('zhangsan'); insert into t_vip(name) values('zhangsan'); insert into t_vip(name) values('zhangsan'); insert into t_vip(name) values('zhangsan');

+----+----------+ | id | name | +----+----------+ | 1 | zhangsan | | 2 | zhangsan | | 3 | zhangsan | | 4 | zhangsan | +----+----------+

会自动生成序号

外键约束(foreign key, FK)*****

业务背景:
   请设计数据库表,来描述“班级和学生”的信息?

    第一种方案:班级和学生存储在一张表中???
    t_student   no(pk)     name    classno     classname------------------------------------------------------
    1          jack      100     高三1班
    2          lucy      100     高三1班
    3          lilei     100    高三1班
    4          hanmeimei 100    高三1班
    5          zhangsan  101   高三2班
    6          lisi      101     高三2班
    7          wangwu    101  高三2班
    8          zhaoliu   101     高三2班
    分析以上方案的缺点:
     数据冗余,空间浪费!!!!
      这个设计是比较失败的!
    ``第二种方案:班级一张表、学生一张表??
    
    ``t_class 班级表
    ``classno(pk)     classname
    ``------------------------------------------------------
    ``100         北京市大兴区亦庄镇第二中学高三1班
    ``101         北京市大兴区亦庄镇第二中学高三1班
  
    ``t_student 学生表
    ``no(pk)     name        cno(FK引用t_class这张表的classno)
    ``------------------------------------------------------
    ``1          jack          100
    ``2          lucy          100
    ``3          lilei         100
    ``4          hanmeimei     100
    ``5          zhangsan      101
    ``6          lisi          101
    ``7          wangwu        101
    ``8          zhaoliu       101

保证只能出现100 和101 加外键约束

当cno字段没有任何约束的时候,可能会导致数据无效。可能出现一个102,但是102班级不存在。
所以为了保证cno字段中的值都是100和101,需要给cno字段添加外键约束。
那么:cno字段就是外键字段。cno字段中的每一个值都是外键值。

注意: t_class是父表 t_student是子表

        删除表的顺序?
            先删子,再删父。
​
        创建表的顺序?
            先创建父,再创建子。
​
        删除数据的顺序?
            先删子,再删父。
​
        插入数据的顺序?
            先插入父,再插入子。

drop table if exists t_student;

drop table if exists t_class;

create table t_class(

classno int primary key,

classname varchar(255)

);

create table t_student(

no int primary key auto_increment,

name varchar(255),

cno int,

foreign key(con) references t_class (classno)

);

思考:子表中的外键引用的父表中的某个字段,被引用的这个字段必须是主键吗?不一定是主键,但至少具有unique约束。不能重复*

    测试:外键可以为NULL吗?
        外键值可以为NULL。

事务******

事务就是一个完整的业务逻辑

什么是一个完整的业务逻辑?

A向b转10k,A-10k(update),b+10k(upda)就是个完整的业务逻辑

以上的操作是一个最小的工作单元,同时成功或者失败,不可再分

两个update要同时成功或者失败

只有DML语句才有事务

insert delete update

因为只有以上操作对数据库中数据进行增删改,只要操作一旦涉及到数据增删改,就一定要考虑安全问题。数据安全第一位!!!!

假设所有业务只要一条DML语句完成,还有必要存在事务机制吗?

正是因为某件事务需要多个DML语句联合起来完成,如果任何一件复杂的事都能一条DML语句完成,事务就没有存在的价值了。

说道本质上,一个事务就是多条DML语句同时成功或者同时失败。

事务是怎么做到多条DML语句同时成功与失败呢?

InnoDB存储引擎:提供一组用来记录事务性活动的日志文件

事务开启了:

insert

insert

delete

update

事务结束了:

事务执行过程中每一条DML都会记录到“事务性活动日志文件中”

事务执行过程中,可以提交事务,也可以回滚事务。

提交事务?

清空事务性活动的日志文件,将数据全部彻底持久化到数据库中

提交事务标志着,事务的结束。并且是一种全部成功的结束。

回滚事务?

将之前所有的DML操作全部撤销,并且清空事务性活动的日志文件

回滚事务标志着事务的结束,并且是一种全部失败的结束

怎么提交,回滚事务?

提交事务:commit;

回滚事务:rollback;(只能回滚到上一次的提交点,所以mysql回滚不了)

事务对应的英语单词是:transaction

测试一下。mysql中默认的事务行为:

mysql默认情况下自动提交事务,每执行一条DML语句就提交一次

其实自动提交是不符合实际开发情况的,可以先用 start transaction,再用 commit提交

怎么关闭自动提交机制?

先执行:start transaction;

事务的四个特性

A:原子性

说明事务是最小的工作单元不可再分

C:一致性

所有事务要求,在同一事务当中,所有事务必须同时成功,或者同时失败,以保证数据的一致性。

I: 隔离线

A事务和B事务之间有一定的隔离,教室A与教室B之间有一道墙,之间有隔性。多线程访问同一张表一样。

D:持久性

事务最终结束的一个保障,事务提交就相当于将没有保存到硬盘中的数据保存在硬盘上

研究一下事务的隔离性

A教室和B教室中间有一道墙,可以很厚也可以很薄,就是事务的隔离级别。

隔离级别越高,表示这道墙越厚,

事务和事务之间的隔离级别有哪些?

  1. 读未提交: read uncommitted(最低隔离级别,没有提交就读到了)

    事务A可以读取事务B未提交的数据

    这种隔离级别存在的问题就是脏读现象(Dirty Read)

    我们称读到了脏数据

    这种隔离级别一般都是理论上的,大多数数据库隔离界别都是二挡起步

  2. 读已提交: read committed(提交之后才能读到)

    事务A只能读取到事务B提交之后的数据,这种隔离级别解决了脏读的现象。

    这种隔离级别存在什么问题?

    不可重复读取数据:在事务开启之后,第一次读到的数据是3条,由于当前B事务还没结束。可能第二次再读取的时候读到的事务是4条。称为不可重复读取。

    这种隔离级别是比较真实的数据,每次读到的数据都比较真实,Oracle默认的隔离级别。

  3. 可重复读: repeatable read(提交之后也读不到)

    事务A开启之后,不管是多久,每一次在A中读取到的数据都是一致的,即使B修改,提交了,A读取到的数据还是没改变。

    解决了不可重复读问题。

    存在的问题?

    可能会出现幻影读。

    每次读取到的数据都是幻象,不够真实。

    早上九点开启了事务,只要事务不结束,到晚上九点,读取到的事务还是那样,读到的是假象,不够绝对的真实。

    mysql默认的隔离级别!!!!!!!!!!!

  4. 序列化/串行化: serializable(最高隔离级别)

    效率最低,解决了所有问题,这种隔离级别表示事务排队,不能并发

    类似于synchronized

    每次读取到的数据都是最真实的,但效率是最低的

验证各种隔离界别

查看隔离级别:select @@tx_isolation;

read uncommitted

read committed

repeatable read

serializable

索引

是在数据库表的字段上加的,为了提高表的查询效率

一张表的一个字段可以添加一个索引,多个字段联合起来也可以添加索引。

一张表没有添加索引的话,会一个一个找目标,全表扫描。

第二种方式是:索引检索。

注意:

在实际中,汉语字典前面的目录是排序的,按照abcdef排序,

因为只有排序了才会有区间查找这一说法。

缩小扫描范围其实就是扫描某个区间罢了,在mysql数据库中,索引也是需要排序的,并且索引的排序和TreeSet数据结构相同,底层是个自平衡的二叉树。在mysql种,索引是个B-Tree数据结构。遵循左小右大原则存放,采用中序遍历方式遍历数据。

索引的实现原理

t_user

id(PK) name


100 zhangsan

123 lisi

99 wangwu

88 zhaoli

101 jack

55 lucy

130 tom

*提醒1:在任何数据库中,主键会自动添加索引**

在mysql中,字段有unique也会自动创建索引

提醒2:在任何数据库中,任何一张表的任何一张记录在硬盘上都有一个物理存储编号

提醒3:在mysql中索引是一个单独的对象,不同的存储引擎以不同的形式存在,在MYISAM存储引擎中,索引存储在一个MYI文件中,在INODB中,索引存储在table space中,MEMORY存储引擎存储在内存中。不管在那个存储引擎,索引在mysql中都是一个自平衡二叉树B-TREE

注意:MySQL中主键和unique字段都会添加索引

什么条件下,会考虑添加索引?

  1. 数据量庞大,需要测试,每一个硬件环境不同。

  1. 经常出现在where后面的字段,总是被扫描

  2. 该字段很少的DML(insert delete update)操作,因为DML之后索引需要重新排序

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

索引的创建和删除

create index emp_ename_index on emp(ename);

drop index emp_ename_index on emp;

查看一个sql语句是否使用了索引进行检索

explain select * from emp where ename='king';

加一个explain

索引的失效

1.模糊查询以%开头

select * from emp where ename like '%T'

这样即使ename添加了索引也不会走索引

原因是以%开头,所以尽量避免模糊查询时以%开始。

这是一种优化的手段

2.使用or时会失效,

如果使用or,两边的条件字段都要有索引才会走索引,如果一边没有,那么另一边的索引也会失效。

所以少用or 也是一种优化手段,用union就行了

3.复合索引

使用复合索引的时候,没有使用左侧的列进行查找,索引失效。

复合索引:多个字段联合起来添加一个索引叫复合索引

create index emp_job_sal_index on emp(job,sal);

举例:

explain select * from emp where job='salesman';

用了索引

下面没用索引

explain select * from emp where sal=800;

4.参与运算

where中索引列参加了运算,索引失效。

create index sal_index on emp(sal);

explain select * from emp where sal+1=800;(失效了,不走索引)

5.使用函数

where中索引使用了函数

explain select * from emp where lower(ename)='smith';

6。。。

7.。。。

索引是各种数据库进行优化的重要手段

优化的时候优先考虑的因素就是索引,索引在数据库种分了很多类:

单一索引:一个字段

复合索引:两个或更多

主键索引:主键加

唯一性索引:unique上加

。。。。。

注意:唯一性比较弱的字段上添加索引用处不大,unique上重复性比较大,索引几乎不起索引,越唯一效率越高。

试图

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

创建视图对象

create view emp_view1 as select * from emp;

删除试图对象

drop view dept2_view;

注意:只有dql语句才能以view形式创建

create view dept2_view as 这边加上的语句必须是DQL语句

试图对象能干什么

可以面向视图对象进行增删改查

对试图对象的增删改查会导致原表被操作

update dept2_view set sal=2000 where deptno=30;

原表也会改变

试图在开发中有什么用

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

create view view_tem as(这边只能是查询语句)

select e.ename ,d.dname

from emp e join dept d on e.deptno=d

一条sql语句很复杂,想直接对其进行操作。就把这条复杂的sql语句以视图对象的形式新建,在需要编写这条sql语句的位置直接使用试图对象,大大简化开发,便于后期维护,只需要修改视图对象所映射的sql语句。

这条语句 我对view_tem 操作时 把 dept表跟emp表都给改了。我日

以后面向视图开放时跟表一样,一样增删改查。视图对象也是存储在硬盘上的不会消失。

DBA常用命令了解一下

重点掌握数据的导入导出

导出:

把数据库导出,到d盘sql文件

mysqldump whx2021 > D:\bjpowernode.sql -uroot -proot

导出表格:

mysqldump whx2021 emp > D:\bjpowernode.sql -uroot -proot

导入:

这个得先创建一个数据库,use数据库,再导入

MariaDB [whx2021]> source C:\Users\90315\Desktop\cs笔记\bjpowernode.sql

(这边不要有英文)

数据库设计三范式

数据库表的设计依据。

1.要求任何一张表必须有主键,每一个字段原子性不可分

2.要求所有非主键字段完全依赖主键,不要产生部分依赖。

第二范式是建立在第一范式之上。

3.建立在第二范式的基础之上,要求所有非主键直接依赖主键,不要产生传递依赖。

声明:面试经常问,一定要熟记在心。

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

第一范式:

最核心最重要的范式,所有表的设计必须满足,

必须有主键,所有主键原子性不能再分。

学生编号 学生姓名 联系方式
  ``------------------------------------------
  ``1001    张三   zs@gmail.com,1359999999
  ``1002    李四   ls@gmail.com,13699999999
  ``1001    王五   ww@163.net,13488888888

1.没有主键

2.联系方式还能再分邮箱,电话

第二范式

要求所有非主键字段完全依赖主键,不要产生部分依赖

学生编号   学生姓名 教师编号 教师姓名
----------------------------------------------------
  1001      张三   001   王老师
  1002      李四   002   赵老师
  1003      王五   001   王老师
  1001      张三   002   赵老师
  ``分析以上的表是否满足第一范式?
    ``不满足第一范式。
 
  ``怎么满足第一范式呢?修改
  学生编号+教师编号(pk)    学生姓名 教师姓名
  ----------------------------------------------------
  1001      001       张三     王老师
  1002      002       李四     赵老师
  1003      001       王五     王老师
  1001      002       张三     赵老师
  学生编号 教师编号,两个字段联合做主键,复合主键(PK: 学生编号+教师编号)
  经过修改之后,以上的表满足了第一范式。但是满足第二范式吗?
    不满足,“张三”依赖1001,“王老师”依赖001,显然产生了部分依赖。
    产生部分依赖有什么缺点?
    数据冗余了。空间浪费了。“张三”重复了,“王老师”重复了。
  ``使用三张表来表示多对多的关系!!!!
    ``学生表
    ``学生编号(pk)  学生名字
    ``------------------------------------
    ``1001          张三
    ``1002          李四
    ``1003          王五
    
    ``教师表
    ``教师编号(pk) 教师姓名
    ``--------------------------------------
    ``001         王老师
    ``002         赵老师
    学生教师关系表
    id(pk)     学生编号(fk)      教师编号(fk)
    --------------------------------------------------
    1            1001            001
    2            1002            002
    3            1003            001
    4            1001            002
 ``背口诀:
    ``多对多怎么设计?  
      ``多对多,三张表,关系表两个外键!!!!!!!!!!!!!!!

第三范式

建立在第二范式的基础之上,要求所有非主键直接依赖主键,不要产生传递依赖。

  ``学生编号(PK) 学生姓名 班级编号 班级名称
  ``---------------------------------------------------------
    ``1001        张三   01     一年一班
    ``1002        李四   02     一年二班
    ``1003        王五   03     一年三班
    ``1004        赵六   03     一年三班
  
  ``以上表的设计是描述:班级和学生的关系。很显然是1对多关系!
  ``一个教室中有多个学生。
  ``分析以上表是否满足第一范式?
    ``满足第一范式,有主键。
  
  ``分析以上表是否满足第二范式?
    ``满足第二范式,因为主键不是复合主键,没有产生部分依赖。主键是单一主键。
  
  ``分析以上表是否满足第三范式?
    ``第三范式要求:不要产生传递依赖!
    ``一年一班依赖01,01依赖1001,产生了传递依赖。
    ``不符合第三范式的要求。产生了数据的冗余。
  
  ``那么应该怎么设计一对多呢?
班级表:一
    ``班级编号(pk)        班级名称
    ``----------------------------------------
    ``01               一年一班
    ``02               一年二班
    ``03               一年三班
    ``学生表:多
    ``学生编号(PK) 学生姓名 班级编号(fk)
    ``-------------------------------------------
    ``1001        张三     01     
    ``1002        李四     02     
    ``1003        王五     03     
    ``1004        赵六     03   
    
    ``背口诀:
      ``一对多,两张表,多的表加外键!!!!!!!!!!!!

总结表的设计:

一对多:

一对多两张表,多的表加外键

多对多:

多对多,三张表,关系表连个外键

一对一:

实际开发中可能存在一张表字段太多太庞大,要拆分,一对一怎么设计?

没有拆分表之前:一张表

 

*#utf8字符集

CREATE DATABASE hsp02 CHARACTER SET utf8;hsp02 #校对规则 utf8_bin 区分大小写,默认的utf8_general_ci不区分大小写 CREATE DATABASE hsp03 CHARACTER SET utf8 COLLATE utf8_bin;

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值