数据库
全称是存储数据的仓库,数据时候有组织的进行存储;简称DataBase(DB)
数据库管理系统
全称是操纵和管理数据库的大型软件 ;简称DataBase Management System(DBMS)
SQL
操纵关系型数据库的编程语言,定义了一套操作关系型数据库统一标准 ;简称Structured Query Language(SQL)
SQL语句可以单行或多行书写 以分号结尾
SQL语句可以使用空格/缩进来增强语句的可读性
MySQL数据库的SQL语句不区分大小写,关键字建议使用大写
注释
数据类型
数值类型
TINYINT
SMALLINT
MEDIUMINT
INT或INTEGER
BIGINT
FLOAT
DOUBLE
DECIMAL
age TINYINT UNSIGNED
score double(4,1)/*表示长度最多是4,小数点位数为1*/
字符串类型
CHAR 定长字符串
定长意思是 规定字符串长度为多少,即使没占用这么多空间 系统会自动帮你补位
**VARCHAR **变长字符串
变长意思是 根据你给的字符串长度 分配具体的空间大小
TINYBLOB
TINYTEXT
BLOB
TEXT
MEDIUMBLOB
MEDIUMTEXT
LONGBLOB
LONGTEXT
CHAR(规定的字符串长度) 性能好
VARCHAR(规定的字符串长度) 性能差
日期类型
查询
1)查询所有数据库(SHOW)
SHOW DATABASES;
2)查询当前数据库(SELECT)
SELECT DATABASE();
创建(CREATE)
/*如果不存在就创建database*/
CREATE DATABASE[IF NOT EXISTS]数据库名[DEFAULT CHARSET 字符集][COLLATE 排序规则];
删除(DROP)
DROP DATABASES[IF EXISTS]; 数据库名
使用(USE)
/*切换访问的数据库*/
USE 数据库名;
查询
1)查询当前数据所有表
SHOW TABLES;
2)查询表结构
DESC 表名;
3)查询指定表的建表语句
SHOW CREATE TABLE 表名;
创建(CREATE)
CREATE TABLE 表名{
字段1 字段1类型[COMMENT 字段1注释],
字段2 字段2类型[COMMENT 字段2注释],
字段3 字段3类型[COMMENT 字段3注释]
}[COMMENT 表注释];
修改(ALTER)
ALTER TABLE 表名 ADD 字段名 类型(长度)[comment 注释][约束];
ALTER TABLE 表名 MODIFY 字段名 新数据类型(长度);
ALTER TABLE 表名 CHANGE 旧字段名 新字段名 类型(长度)[COMMENT 注释] [约束];
ALTER TABLE 表名 DROP 字段名;#删除列
ALTER TABLE 表名 RENAME TO 新表名;
删除
DROP TABLE [IF EXISTS]表名;
TRUNCATE TABLE 表名;
用来对数据库中的数据记录进行**(insert)、(delete)、(update)**操作
添加数据(INSERT)
INSERT INTO 表名 (字段名1,字段名2,...)VALUES(值1,值2,...);
INSERT INTO 表名 VALUES(值1,值2,...);
/*批量插入数据 用逗号隔开*/
INSERT INTO 表名(字段名1,字段名2,...)VALUES(值1,值2,...),(值1,值2,...),(值1,值2,...);
INSERT INTO 表名 VALUES (值1,值2,...),(值1,值2,....),(值1,值2,....);
注意:
1)插入数据时,指定的字段顺序需要与值的顺序是一致的
2)字符串和日期类型应该包含的在引号中
3)插入的数据大小,应该在字段的规定范围内
修改数据(UPDATE)
UPDATE 表名 SET 字段名1=值1,字段名2=值2,...[WHERE 条件];
删除(DELETE)
DELETE FROM 表名[WHERE 条件];
数据查询语言,用来查询(筛选)数据中表的数据
基本查询
SELECT 字段1,字段2,字段3...FROM 表名;
SELECT *FROM 表名(全部字段)#返回查询列表中所有数据
SELECT 字段1[AS 别名1],字段2[AS 别名2]...FROM表名;#别名要用单引号 AS可以省略
SELECT DISTINCT 字段列表 FROM 表名;#将该列的重复的元素去除(去重)
条件查询
SELECT 字段列表 FROM WHERE 条件列表;# where相当于java中if语句 后接条件语句 字段列表=*(所有列)
条件
比较运算符 | 功能 |
---|---|
> | 大于 |
>= | 大于等于 |
< | 小于 |
<= | 小于等于 |
= | 等于 |
<>或!= | 不等于 |
BETWEEN…AND | 在某个范围之内(含最小、最大值) |
IN(…) | 在in之后的列表中的值,多选一 |
LIKE 占位符 | 模糊匹配(匹配_单个字符,%匹配任意个字符) |
IS NULL | 是NULL |
逻辑运算符
逻辑运算符 | 功能 |
---|---|
AND或&& | 并且(多个条件同时成立) |
OR或|| | 或者(多个条件任意一个成立) |
NOT或! | 非,不是 |
聚合函数
介绍
将一列数据作为一个整体
常见聚合函数
函数 | 功能 |
---|---|
count | 统计数量 |
max | 最大值 |
min | 最小值 |
avg | 平均值 |
sum | 求和 |
语法
SELECT 聚合函数 from 表名;
# SELECT COUNT(*)FROM EMP;
#SELECT COUNT(ID)FROM EMP;
#聚合函数传进去的是字段
注意:null值不参与聚合函数的运算
分组查询(GROUP BY)
语法
SELECT 字段列表 FROM 表名[WHERE 条件]GROUP BY 分组字段名[HAVING 分组后过滤条件];
SELECT gender,count(*)from emp GROUP BY gender;
#查询效果是 根据性别分组 统计男女的数量
SELECT gender,AVG(age)FROM emp GROUP BY gender;
#查询效果是 根据性别分组 统计男女的平均年龄
SELECT address,COUNT(*)FROM emp WHERE age<xxx GROUP BY address;
#查询效果是 根据地址分组 统计年龄小于xxx的人数
SELECT address,COUNT(*) address_count FROM emp WHERE age<xxx GROUP BY address HAVING address_count>X;
#上面一条语句的基础上再次筛选having
HAING 和WHERE区别
注意
排序查询(ORDER BY)
语法
#支持多字段排序
SELECT 字段列表 FROM 表名 ORDER BY 字段1 排序方1,字段2 排序方式2
SELECT * FROM emp ORDER BY age desc;#降序
SELECT * FROM emp ORDER BY age asc;#升序
SELECT * FROM emp ORDER BY age asc,entrydate desc;
排序方式
ASC:升序(默认值)
DESC:降序
注意:如果是多字段查询时,当第一个字段值相同时,才会根据第二个字段进行排序
分页查询(LIMIT)
语法
SELECT 字段列表 FROM LIMIT 起始索引,查询记录数;#两个参数
注意
视频练习
SELECT age FROM emp BETWEEN 20 AND 23;
SELECT * FROM emp WHERE gender='男'and (20<=age<=40) and like '___';#加个括号显得更有清晰一些
SELECT gender,count(*)FROM emp WHERE age<60 GROUP BY gender;
SELECT age,name FROM emp where age<=35 ORDER BY age HAVING entryDate desc;
SELECT gender FROM emp where gender='男' 20<age<40 ORDER BY age ,HAVING entryDate desc LIMIT 5;
详情请看这篇博客:SQL的执行顺序_不想做靓仔的博客-CSDN博客_sql执行顺序
编写顺序
SELECT->FROM->WHERE->GROUP BY->HAVING->ORDER BY->LIMIT
执行顺序==(重点)==
FROM->WHERE->GROUP BY->HAVING->SELECT->ORDER BY->LIMIT
聚合函数的执行在GROUP BY之后,HAVING之前
用来管理数据库用户,控制数据库的访问权限
查询用户
USE mysql;
SELECT *FROM user;
创建用户
CREATE USER '用户名'@'主机名' IDENTIFIED BY '密码'; #主机名是'localhost'
修改用户密码
ALTER USER '用户名'@'主机名' IDENTIFIED WITH mysql_native_password BY '新密码';
删除用户
DROP USER '用户名'@'主机名';
注意:
权限 | 说明 |
---|---|
ALL,ALL PRIVILEGES | 所有权限 |
SELECT | 查询数据 |
INSERT | 插入数据 |
UPDATE | 修改数据 |
DELETE | 删除数据 |
ALTER | 修改表 |
DROP | 删除数据库/表/视图 |
CREATE | 创建数据库/表 |
查询权限
SHOW GRANTS FOR '用户名'@'主机名';
授予权限
GRANT 权限列表 ON 数据库名.表名 TO '用户名'@'主机名';
GRANT ALL ON xxx.xxx TO '用户名'@'主机名';
撤销权限
REVOKE 权限列表 ON 数据苦命.表名 FROM '用户名'@'主机名';
注意:
常用函数
函数 | 功能 |
---|---|
CONCAT(S1,S2,…Sn) | 字符串拼接,将s1,s2,…sn拼接成一个字符串 |
LOWER(str) | 将字符串str全部转成小写 |
UPPER(str) | 将字符串str全部转成大写 |
LPAD(str,n,pad) | 左填充,用字符串pad对str的左边进行填充,达到n个字符串长度 |
RPAD(str,n,pad) | 右填充,用字符串pad对str的右边进行填充,达到n个字符串长度 |
TRIM(str) | 去掉字符串头部和尾部的空格 |
SUBSTRING(str,start,len) | 返回从字符串str从start位置起len个长度的字符串 |
SELECT 函数(参数);
常用函数
函数 | 功能 |
---|---|
CEIL(x) | 向上取整 |
FLOOR(x) | 向下取整 |
MOD(x,y) | 返回x/y的模 |
RAND() | 返回0~1的随机数 |
ROUND(x,y) | 求参数x的四舍五入的值,保留y位小数 |
常用函数
函数 | 功能 |
---|---|
CURDATE() | 返回当前日期 |
CURTIME() | 返回当前时间 |
NOW() | 返回当前日期和时间 |
YEAR(date) | 返回当前指定date的年份 |
MONTH(date) | 返回当前指定date的月份 |
DAY(date) | 返回当前指定date的日期 |
DATE_ADD(date,INTERVAL_EXPR type) | 返回一个日期/时间加上一个时间间隔expr后的时间值 |
DATEDIFF(date1,date2) | 返回起始时间date1和结束时间date2之间的天数 |
SELECT date_add(now(),INTERVAL 70 YEAR);
#查询员工的入职天数
SELECT name,diff(now(),entrydate) as entrydayscount FROM emp Group By entrydayscount
SELECT name,DATEDIFF(NOW(),'2000-11-12')FROM emp
常见函数
函数 | 功能 |
---|---|
IF(Value,t,f) | 如果value为true,则返回t,否则返回f |
IFNULL(Value1,Value2) | 如果Value1不为空(空=null),则返回value1,否则返回value2 |
CASE WHEN [val1]THEN[res1]…ELSE[default]END | 如果val1为true,返回res1,否则返回default默认值 |
CASE [expr]WHEN[val]THEN[res1]…ELSE[default]END | 如果**expr(表达式)**的值等于val1,返回res1,…否则返回default默认值 |
SELECT name,(case workaddress when '北京'then'一线城市'when '上海'then'一线城市'else'二线城市'end)asd '工作地址'
SELECT id,name,(case when math>=85 then '优秀' when math>=60 then '及格'else '不及格 'end)as '数学'),
(case when English>=85 then '优秀' when English>=60 then '及格'else '不及格 'end)as '英语'),
(case when Chinese>=85 then '优秀' when Chinese>=60 then '及格'else '不及格 'end)as '语文')
FROM score;
概念
约束是作用表中字段上的规则,用于限制存储在表中的数据
作用
保证数据库中数据的正确性、有效性和完整性
分类
约束 | 描述 | 关键字 |
---|---|---|
非空约束 | 限制该字段的数据不能为null | NOT NULL |
唯一约束 | 保证该字段的所有数据都是唯一,不重复的 | UNIQUE |
主键约束 | 主键是一行数据的唯一标识,要求非空且唯一 | PRIMARY KEY |
默认约束 | 保存数据时,如果未指定该字段的值,则采用默认值 | DEFAULT |
检查约束(8.0.16) | 保证字段值满足某一个条件(逻辑表达式+比较运算符) | CHECK |
外键约束 | 用来让两张表的数据中之间建立连接,保证数据的一致性和完整性 | FOREIGN KEY |
注意:约束是作用在表中字段上的,可以在创建表/修改表的时候添加约束
create table user(
id int primary key auto_increment comment '主键',
name varchar(10) not null comment '名字',
age int check ( age>0&&age<120 ) comment '年龄',# mysql 版本要在8.0才支持该语句
status char(1) default '1'comment '状态',
gemder char(1) comment'性别'
)comment '用户表';
#建表前添加外键
CREATE TABLE 表名{
字段名 数据类型,
...
[CONSTRAINT][外键名称]FOREIGN KEY(外键字段名)REFERENCES 主表(主表列名)
};
#建表后进行添加外键
ALTER TABLE 表名 ADD CONSTRAINT 外键名称 FOREIGN KEY (外键字段名)REFERENCES 主表(主表列名);#表名连接主表
ALTER TABLE 表名 ADD CONSTRAINT FK_表名_外键字段名 FOREIGN KEY (外键字段名)REFERENCES 主(父)表(主表列名);
ALTER TABLE 表名 DROP FOREIGN KEY 外键名称;
行为 | 说明 |
---|---|
NO ACTION | 当父表中删除/更新对应纪录时,首先检查该记录是否有对应外键,如果有则不允许删除/更新。 |
RESTRICT | 同上 |
CASCADE | 当父表中删除/更新对应纪录时,首先检查该记录是否有对应外键,如果有则也删除/更新外键在字表中的记录 |
SET NULL | 当父表中删除/更新对应纪录时,首先检查该记录是否有对应外键,如果有则设置字表中该外键值为null |
SET DEFAULT | 父表有变更时,字表将外键列设置成一个默认值(Innodb不支持) |
ALTER TABLE 表名 ADD CONSTRAINT 外键名称 FOREIGN KEY (外键字段)References 主表名(字表字段名) ON UPDATE CASCADE ON DELETE CASCADE;
概述:由于业务之间相互关联,所以各个表结构之间也存在着各种联系,基本分为三种
一对多(多对一)
多对多
一对一
概述:指从多张表中查询数据
笛卡尔积:笛卡尔乘积是指在数学中个,两个集合A集合和B集合的所有组合情况。(多表查询时,需要消除无效的笛卡尔积(连接条件))
#多表查询
SELECT *FROM 父表,外表;
多表查询分类
连接查询
内连接
相当于查询A、B交集部分数据
外连接
自连接
当前表与自身的连接查询,自连接必须使用表别名
联合查询
子查询
SELECT 字段列表 FROM 表1,表2 WHERE 条件...;
#视频例子 emp员工表 dept部门表
SELECT emp.name,dept.name FROM emp,dept WHERE emp.dept_id=dept.id;
SELECT 字段列表 FROM 表1,[INNER] JOIN 表2 ON 连接条件;
#视频例子
SELECT e.name,d.name FROM emp e INNER JOIN dept d ON e.dept_id=d.id;
SELECT 字段列表 FROM 表1 LEFT [OUTER] JOIN 表2 ON 条件 #字段列表根据需求可进行优化 因为按照sql语句的执行属性可知select是在后面执行
相当于查询表1(左表)的所有数据和包含表1和表2交集部分的数据
SELECT 字段列表 FROM 表1 RIGHT [OUTER] JOIN 表2 ON 条件
相当于查询表2(右表)的所有数据和包含表1和表2交集部分的数据
# 把一张表看做成两张表 通过唯一的id做为自连接的条件 managerid=id
# 自连接必须给表名取别名!!!
SELECT 字段列表 FROM 表A 别名A JOIN 表A 别名B ON 条件...;
SELECT a.name,b.name FROM emp a JOIN emp b ON a.managerid=b.id;
定义
对于联合查询,就是把多次查询的结果合并起来,形成一个新的查询结果集。
关键词
# 作为单独一句 在两个sql语句查询中间
UNION #将查询的结果合并时,进行去重
UNION ALL #直接将查询的结果进行合并
注意
SELECT * FROM t1 WHERE column1=(SELECT column1 FROM t2);
#子查询外部的语句可以是INSERT/UPDATE/DELETE/SELECT的任何一个
查询结果分类
根据子查询位置
标量子查询
定义: 子查询返回的结果是单个值(数字,字符串,日期等),最简单的形式,这种子查询称为标量子查询
常用操作符:= 、<>、> 、>=、 < 、<=
案例展示
# emp员工信息表
# dept部门表
# 要求查询具体部门对应的员工信息 前提员工表和部门表是已经建立了连接(foreign key)
# 分析 首先得知道具体部门的部门ID 进而查询该部门的员工信息
# 可以两种sql写法
SELECT id FROM dept WHERE name='具体的部门名';
SELECT * FROM emp WHERE dept_id ="上条语句的结果";
# 所以可以整合成一句 形成嵌套
SELECT * FROM emp WHERE dept_id=(SELECT id FROM dept WHERE name='具体的部门名');
列子查询
操作符 | 描述 |
---|---|
IN | 在指定的集合范围之内,多选一 |
NOT IN | 不在指定的集合范围之内 |
ANY | 子查询返回列表中,有任意一个满足即可 |
SOME | 与ANY等同,使用SOME的地方都可以使用ANY |
ALL | 子查询返回列表的所有值都必须满足 |
#查询比财务部所有人工资都高的员工信息
#将获取信息的问题拆分化 在通过嵌套进行优化 形成一句sql语句
# 获取财务部的部门id
SELECT id FROM dept WHERE name ='财务部';
# 获取财务中所有人的工资
SELECT salary FROM emp WHERE id=(SELECT id FROM dept WHERE name ='财务部');
# 获取比财务部所有员工工资都高的员工信息
SELECT * FROM emp WHERE salary>ALL SELECT salary FROM emp WHERE id=(SELECT id FROM dept WHERE name ='财务部');
行子查询
# 查询张无忌的薪资及直属领导相同的员工信息
SELECT salary managerid FROM emp WHERE name="张无忌";
SELECT *FROM emp WHERE (salary,managerid)=(SELECT salary managerid FROM emp WHERE name="张无忌");
#返回的结果是一行多列 对应的是salary和managerID
表子查询
``sql
#查询入职日期是“2006-01-01”之后的员工信息和部门信息
SELECT * FROM emp where entrydate>‘2006-01-01’;
SELECT e.,d. FROM (SELECT * FROM emp where entrydate>‘2006-01-01’) e LEFT JOIN dept d on e.dept_id=d.id;
事务是一组操作的集合,他是一个不可分割的工作单位,事务会把所有的操作作为一个整体一起向系统提交或撤销操作请求,即这些操作要么同时成功,要么同时失败。
#第一种 设置autocommit值
SELECT @@autocommit;# autocommit=0表示手动提交 1表示自动提交 修改值:set autocommit=0/1
SET @@autocommit=0;
#第二种 开启事务
START TRANSACTION 或 BEGIN
COMMIT;#出错不运行执行commit指令
ROLLBACK;#出错则进行回滚rollback
create table account(
id int auto_increment primary key comment '主键',
name varchar(10) comment '姓名',
money int comment '金额'
)comment '个人账户';
insert into account(id, name, money) VALUES (null,'张三',2000),(null,'李四',2000);
update account set money=2000 where name='李四'or name='张三';
set @@autocommit=0;#手动提交
select * from account where name='李四' or name='张三';
update account set money = money-1000 where name='李四';
#报错指令...
update account set money=money+1000 where name='张三';
commit;#执行结果无报错 则可以执行commit操作(手动提交)
#回滚事务
rollback;
事务是不可分割的最小操作单元,要么成功,要么失败
事务完成时,必须是所有的数据都保持一致状态
数据库系统提供的隔离机制,保证事务在不受外部并发操作影响的独立环境下运行
就好比:有多个事务对同一个的数据库进行数据操作,并行操作的事务A不会影响事务B对数据库的操作!
事务一旦提交或回滚,它对数据库中的数据的改变就是永久的(将改变的数据存在电脑磁盘)
问题 | 描述 |
---|---|
脏读 | 一个事务读到另一个事务还没有提交的数据 |
不可重复读 | 一个事务先后读取同一条记录,但两次读取的数据不同,称之为不可重复读 |
幻读 | 一个事务按照条件查询数据时,没有对应的数据行,但是在插入数据时,又发现这行数据已经存在,好像出现了”幻影“ |
这些都是由于多个并行的事务引发的问题…
隔离级别 | 脏读 | 不可重复读 | 幻读 |
---|---|---|---|
Read uncommitted | √ | √ | √ |
Read committed | × | √ | √ |
Repeatable Read**(默认)** | × | × | √ |
Serializable | × | × | × |
注意:性能越来越差,数据安全越来越高
#查看事务隔离级别
SELECT @@transaction_isolation;
#设置事务隔离级别
SET [SESSION|GLOBAL] TRANSACTION ISOLATION LEVEL {READ UNCOMMITTED|READ COMMITTED|REPEATABLE READ|SERIALIZABLE};
#SESSION(会话级别)指的是当前客户端
#GLOBAL(全局级别) 指的是所有的客户端