1.什么是SQL ?
Structured Query Language
:结构化查询语言
其实就是定义了操作所有关系型数据库的规则。每一种数据库操作的方式存在不一样的地方,称为“方言”。
2.SQL分类
1> DDL(Data Definition Language)数据定义语信
用来定义数据库对象:数据库,表,列等。关键字: create, drop,alter 等
2> DML(Data Manipulation Language)数据操作语言
用来对数据库中表的数据进行增删改。关键字: insert, delete, update等
3> DQL(Data Query Language)数据查询语言
用来查询数据库中表的记录(数据)。关键字: select,where等
4> DCL(Data Control Language)数据控制语言
用来定义数据库的访问权限和安全级别及创建用户。关键字: GRANT,REVOKE等
3.操作数据库
连接mysql: mysql -u root(用户名) -p 退出: exit;
1> 创建数据库 create database dbtest;
判断有无,再创建 create database if not exists dbtest;
并指定字符集 create database if not exists dbtest2 default character set utf8mb4 collate utf8mb4_0900_ai_ci;
2> 查询所有数据库 show databases;
查询单个数据库 show create database dbtest;
3> 修改数据库 alter database dbtest character set gbk;
4> 删除数据库 drop database dbtest2;
判断有无,存在删除 drop database if exists dbtest2;
5> 使用数据库 use dbtest;
查询当前正在使用的数据库 select database();
4.操作表
-- 1.创建表 create table 表名
-- CREATE TABLE tbtest(
-- id INT,
-- name VARCHAR(20), # varchar 字符串 最大20个字符
-- score DOUBLE(5,2), # double 小数类型 数值长度为5,保留两位小数
-- birthday DATE, # 日期 yyyy-MM-dd
-- addtime TIMESTAMP # timestamp 时间戳 yyyy-MM-dd HH:mm:ss
-- );
-- 复制表
-- CREATE TABLE tbtest2 like tbtest;
-- 2.查询表
-- show tables;
-- 查询表结构
-- desc tbtest;
-- 3.修改
-- ALTER TABLE tbtest2 rename to tbtest3; # 修改表名
-- ALTER TABLE tbtest3 character set utf8; # 修改字符集
-- ALTER TABLE tbtest add firstname varchar(50); # 添加一列
-- ALTER TABLE tbtest change firstname lastname varchar(10); # 修改列名 将firstname改为lastname,新数据类型varchar(10)
-- ALTER TABLE tbtest modify lastname varchar(20); # 修改列数据类型
-- ALTER TABLE tbtest drop lastname; # 删除列
-- 4.删除
-- drop table tbtest3;
-- drop table if exists tbtest3;
5.操作表中数据
-- 1.新增
-- insert into tbtest(id,name,score) values (1,"小波",80); # 列名和值一一对应
-- insert into tbtest values (2,"小虎",90,"2020-08-22","2020-08-23 00:00:34","虎"); # 不定义类名则默认添加所有列
-- 2.修改
-- update tbtest set name="小小",score=90 where id=1;
-- 3.删除
-- delete from tbtest where name="小小";
-- delete from tbtest; # 不加删除条件则删除表中所有数据 - 不推荐 - 若要删除所有使用以下效率更高:
-- truncate table tbtest; # 表示 先删除表,然后再创建一个一样的表
5.1 查询
-- insert into tbtest values (0,"波波","90","2020-08-22","2020-08-22 00:00:20","徐");
-- insert into tbtest values (1,"天天","80","2019-08-22","2020-08-22 00:00:20","吴");
-- insert into tbtest values (2,"林林","70","2018-08-22","2020-08-22 00:00:20","赵");
-- insert into tbtest values (3,"天波","90","2017-08-22","2020-08-22 00:00:20","周");
-- insert into tbtest values (4,"林波","90","2016-08-22","2020-08-22 00:00:20","李");
-- insert into tbtest values (5,"天林","65","2015-08-22","2020-08-22 00:00:20","周");
-- insert into tbtest values (6,"波林","68","2014-08-22","2020-08-22 00:00:20","李");
-- insert into tbtest values (7,"林天","90","2013-08-22","2020-08-22 00:00:20","徐");
-- insert into tbtest values (8,"波天",null,"2012-08-22","2020-08-22 00:00:20","徐");
-- select * from tbtest;
-- 5.1.1 排序查询 order by
-- select * from tbtest order by score; # 默认升序 asc
-- select * from tbtest order by score desc; # 降序
-- select * from tbtest order by score,birthday; # 多个排序条件,前一个相同才会判断后一个
-- 5.1.2 聚合函数 排除null值
-- select min(score) from tbtest; # 最小值
-- select max(score) from tbtest; # 最大值
-- select sum(score) from tbtest; # 计算和
-- select avg(score) from tbtest; # 平均值
-- select avg(ifnull(score,0)) from tbtest; # ifnull()第一个表达式是否为 NULL,如果为 NULL 则返回第二个参数的值
-- 5.1.3 分组查询
-- select avg(score) from tbtest group by lastname; # 按照lastname分组
-- select lastname,avg(score) from tbtest group by lastname; # 按照lastname分组
-- select lastname,avg(score) from tbtest where score > 70 group by lastname;
-- select lastname,avg(score) from tbtest where score > 70 group by lastname having avg(score) > 80;
-- where 与 having 区别:
-- 1. where 在分组前限定,不满足条件不参与分组;having 在分组后限定,不满足条件不会被查询出来;
-- 2. where 后不可以跟聚合函数;having 可以进行聚合函数的判断;
-- 5.1.4 分页查询 limit 是MySQL "方言"
-- select * from tbtest limit 0,3; -- 第一页
-- select * from tbtest limit 3,3; -- 第二页
-- select distinct score from tbtest; # 去除重复 distinct必须放在查询字段开头 *常用于查询不重复记录的条数
-- select count(distinct score) from tbtest;
-- select score as "分数" from tbtest; # 起别名 as 可以省略
-- select score "分数" from tbtest;
-- 5.1.5 条件查询 where
-- select * from tbtest where (score is null); # 只能通过 is null 来判断null值
-- like 模糊查询 _:单个任意字符; %:多个任意字符
-- select * from tbtest where (name like "%波%" and lastname like "徐"); #查询名称含有波 同时lastname是徐
-- select * from tbtest where (name like "_波" and lastname like "徐"); #查询名称第二字是波 同时lastname是徐
-- select * from tbtest where (name like "%波%" or lastname like "徐"); #查询名称含有波 或者lastname是徐
6.约束 设置约束时当存在数据不符合约束将报错
-- 1.非空约束 not null
-- a.创建时添加
-- create table student(
-- id int,
-- name varchar(20) not null
-- );
-- b.删除
-- alter table student modify name varchar(20);
-- insert into student values(1,null);
-- truncate table student;
-- c.添加
-- alter table student modify name varchar(20) not null;
-- drop table student;
-- 2.唯一约束 unique
-- a.创建时添加
-- create table student(
-- id int unique,
-- name varchar(20)
-- );
-- insert into student values(1,"波波");
-- b.删除
-- alter table student drop index id;
-- insert into student values(1,"波波2");
-- truncate table student;
-- c.添加
-- alter table student modify id int unique;
-- drop table student;
-- 3.主键约束 primary key -- 非空且唯一;一张表只能有一个字段为主键;主键就是表中的唯一标识.
-- a.创建时添加
-- create table student(
-- id int primary key,
-- name varchar(20)
-- );
-- b.删除
-- alter table student drop primary key;
-- c.添加
-- alter table student modify id int primary key;
-- insert into student values(1,"波波");
-- drop table student;
-- {
-- 3.1自动增长 auto_increment 如果某一列是数值类型,使用 auto_increment 可以完成值的自动增长
-- a.创建时添加
-- create table student(
-- id int primary key auto_increment, # 设置主键并自动增长
-- name varchar(20)
-- );
-- insert into student values(null,"波波"); # 因为有自动增长,所以赋值null会自动赋值上一条值+1
-- b.删除
-- alter table student modify id int;
-- c.添加
-- alter table student modify id int auto_increment;
-- }
-- 4.外键约束 foreign key 表与表产生关系,从而保证数据的正确性
-- a.创建时添加
-- create table xx(
-- ...
-- constraint 外键名称 foreign key (外键列名称) references 外表名称(外表列名称)
-- );
-- {演示:创建一个worker表,外键关联
-- create table worker(
-- id int primary key auto_increment,
-- location varchar(50) not null,
-- worktime int
-- );
-- 创建3条数据
-- insert into worker values (1,"南京",8);
-- insert into worker values (2,"成都",6);
-- insert into worker values (3,"北京",10);
-- 给tbtest表添加一列worker
-- alter table tbtest add worker int;
-- *将列worker 外键关联到worker表
-- alter table tbtest add constraint worker_fk foreign key (worker) references worker(id);
-- 更改将tbtest表中所有含"波"的worker=3,再将所有含"林"的worker=1
-- update tbtest set worker=3 where (name like "%波%");
-- update tbtest set worker=1 where (name like "%林%");
-- }
-- b.添加
-- alter table tbtest add constraint 外键名称 foreign key (外键列名称) references 外表名称(外表列名称);
-- c.删除 - 注意是 外键名称
-- alter table tbtest drop foreign key worker_fk;
-- 4.1 级联操作 - 慎重,慎重,慎重
-- 添加级联
-- alter table tbtest add constraint 外键名称 foreign key (外键列名称) references 外表名称(外表列名称) on update cascade on delete cascade;
-- a.级联更新:on update cascade
-- a.级联删除:on delete cascade
-- 先删除,然后同时设置级联更新和级联删除
-- alter table tbtest add constraint worker_fk foreign key (worker) references worker(id) on update cascade on delete cascade;
-- 更新worker 将id 1换成5, tbtest中外键关联worker=1的数据全部变成了worker=5
-- update worker set id=5 where id=1;
-- 删除worker表中的id=3, 直接导致tbtest中外键关联worker=3的数据被全部删除,级联设置一定要慎重啊
-- delete from worker where id=3;
7.多表查询
-- 笛卡尔积:取两个集合的所有组成情况;要完成多表查询,需要消除无用数据。
-- select * from tbtest,worker;
-- 1.内连接查询
-- a.隐式内连接
-- select tbtest.id,tbtest.`name`,worker.location from tbtest,worker where tbtest.worker = worker.id;
-- b.显式内连接
-- select * from tbtest join worker on tbtest.worker = worker.id;
-- b.外连接查询 ✔️ left:左外连接,查询的是左表所有数据以及其交集部分 right:右外连接,查询的是右表所有数据以及其交集部分
-- select * from tbtest t1 left join worker t2 on t1.worker = t2.id; # 当某行t1.worker无值时,左右结果就不一样
-- select * from tbtest t1 right join worker t2 on t1.worker = t2.id;
-- 2.子查询 ✔️ 查询嵌套查询 ()
-- a.当子查询结果是单行单列(一个值)的时候直接用= 就是一个值比对
-- select * from tbtest where worker = (select id from worker where worktime = 6);
-- b.当子查询结果为多行单列(数组)的时候用in
-- select * from tbtest where worker in (select id from worker where worktime = 6 or worktime = 8);
-- c.子查询结果是多行多列(还是一个表)的时候 那就按查表的方式写
-- select * from tbtest t1,(select * from worker where worktime = 8) t2 where t1.worker = t2.id;
8.数据库的设计
一对一:在任意一方添加唯一(unique)外键指向另一方的主键。场景如:用户和身份证
一对多:在多的一方建立外键,指向一的一方的主键。场景如:部门和员工
多对多:需要借助第三张中间表。中间表至少包含两个字段,这两个字段作为第三张表的外键,分别指向两张表的主键。场景如:学生和课程
create table xy(
xx int,
yy int,
primary key (xx,yy), #复合主键
foreign key (xx) references test(id),
foreign key (yy) references tbtest(id)
);
数据库范式
第一范式(1NF):每一列都是不可分割的原子数据项
第二范式(2NF):在1NF的基础上,非码属性必须完全依赖于候选码(在1NF基础上消除非主属性对主码的部分函数依赖)
第三范式(3NF):在2NF基础上,任何非主属性不依赖于其它非主属性(在2NF基础上消除传递依赖)
*几个概念:
1.函数依赖: A-->B,如果通过A属性(属性组)的值,可以确定唯一B属性的值。 则称B依赖于A
2.完全函数依赖: A-->B,如果A是一个属性组,则B属性值得确定出要依赖于A属性组中所有的属性值。
3.部分函数依赖: A-->B,如果A是一个属性组,则B属性值行确定只需要依赖于A属性组中某一些值即可。
4.传递函数依赖: A-->B, B-->C。如果通过A属性(属性组)的值,可以确定唯一B属性的值,在通过B属性(属性组)的值可以确定唯一C属性的值,则称C传递函数依赖于A
5.码:如果在一张表中,一个属性或属性组,被其他所有属性所完全依赖,则称这个属性(属性组)为该表的码
6.主属性:码属性组中的所有属性
7.非主属性:除过码属性组的属性
9.事务
1.概念:
访问并可能操作各种数据项的一个数据库操作序列,这些操作要么全部执行,要么全部不执行,是一个不可分割的工作单位。事务由事务开始与事务结束之间执行的全部数据库操作组成。
2.操作:
a.开启事务:start transaction;
b.回滚:rollback;
c.提交:commit;
* MySQL数据库中事务默认自动提交;Oracle数据库默认手动提交事务;
* 一条DML(增删改)语句会自动提交一次事务;
* 查看事务的默认提交方式: select @@autocommit; # 1 代表自动提交 0 代表手动提交
* 修改默认提交方式: set @@autocommit = 0;
3.事务的四大特征:
1> 原子性(Atomicity):不可分割的最小操作单位,要么同时成功,要么同时失败。
2> 隔离性(Isolation):多个事务之间相互独立。
3> 持久性(Durability):当事务提交或者回滚后,数据库会持久化的保存数据。
4> 一致性(Consistency):几个并行执行的事务,其执行结果必须与按某一顺序 串行执行的结果相一致。
4.事务的隔离级别
* 概念:多个事务之间隔离的,相互独立的。但是如果多个事务操作同一批数据,则会引发一些问题, 设置不同的隔离级别就可以解决这些问题。
* 存在问题:
1.脏读:一个事务,读取到另一个事务中没有提交的数据
2.不可重复读(虚读) :在同一个事务中,两次读取到的数据不一样。
3.幻读:一个事务操作(DML)数据表中所有记录,另一个事务添加了一条数据,则第一个事务查询不到自己的修改。
* 隔离级别:
1. read uncommitted :读未提交
*产生的问题:脏读、不可重复读、幻读
2. read committed :读已提交(Oracle默认)
*产生的问题:不可重复读、幻读
3. repeatable read: 可重复读(MySQL默认)
*产生的问题:幻读
4. serializable :串行化
*可以解决所有的问题
*注意:隔离级别从小到大安全性越来越高,但是效率越来越低
*数据库查询隔离级别:
* select @@tx_isolation;