- 关系型数据库
- 非关系型数据库
SQL : Structured Query Language
- DDL: Data Defination Language
- DML: Data Manipulation Language
- DCL: Data Control Language
启动服务
``` bash mysql -h 主机名 -P 端口号 -u 用户名 -p密码
mysql -h localhost -P 3306 -u root -p Enter password:**
#也可以使用MySQL自带的终端启动工具打开 #密码不要忘了,一般就是123456
mysql -V mysql –version
exit quit
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
``` sql
create database db_name;
use db_name;
show tables;
show tables from db_name;
create table t_name (
field1 类型,
field2 类型
);
select * from t_name;
insert int t_name values();
/*查看创建表的详细信息*/
show create table t_name\G
drop table t_name;
drop datebase db_name;
SELECT
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
select 列名 from table_name;
select * from tb_name;
-- 别名,不建议省略AS
SELECT long_name AS name,
commission_pct comm,
FROM tb_name;
-- 甚至可以加入算式
SELECT last_name "Name",
salary*12 "Annual Salary"
FROM em_table;
SELECT DISTINCT a_id,salary
FROM tb_name;
-- MySQL中,空值不等于空字符串,空战占用空间
SELECT emp_id,salary,commission_pct, 12 * salarry * (1 + commission_pct) "anual_sal"
FROM tb_name;
-- 也有这种需求,增加一个new 字段
SELECT 'A表' as new_field , l_name
FROM tb_name;
-- 显示表结构
DESC tb_name;
DESCRIBE tb_name;
/*
- Field:表示字段名称。
- Type:表示字段类型,这里 barcode、goodsname 是文本型的,price 是整数类型的。
- Null:表示该列是否可以存储NULL值。
- Key:表示该列是否已编制索引。PRI表示该列是表主键的一部分;UNI表示该列是UNIQUE索引的一部分;MUL表示在列中某个给定值允许出现多次。
- Default:表示该列是否有默认值,如果有,那么值是多少。
- Extra:表示可以获取的与给定列有关的附加信息,例如AUTO_INCREMENT等。
*/
-- 过滤
SELECT * FROM tb_name
WHERE 条件;
运算符
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
/*
在Java中,+的左右两边如果有字符串,那么表示字符串的拼接。但是在MySQL中+只表示数值相加。如果遇到非数值类型,先尝试转成数值,如果转失败,就按0计算。(补充:MySQL中字符串拼接要使用字符串函数CONCAT()实现)
整数与浮点数进行运算也会有转型
+ - * / % MOD
*/
SELECT employee_id,salary,salary * 12 annual_sal
FROM employees;
-- 比较运算符
SELECT FROM tb_name WHERE A=B
SELECT FROM tb_name WHERE A<=>B --安全等于运算符
<> !=
=
-- 等号两边比较,若类型相同的时候
-- 如果有一个是字符串,则自动转字符串再进行比较
-- 如果有一个为NULL,那么结果也是NULL
<=>
-- 安全运算符对NULL进行判断
SELECT com_id ,comss_id, FROM employees WHERE comm_id <=>
0.40
!= <>
-- 对于这些不等于的判断,没有空值判断,如果出现空值,结果就是空值
-- 非类型的运算符
IS NULL;
IS NOTNULL;
LEAST; -- return min
GREATEST -- return max
ISNULL
IN -- 判断是否在表中
NOT IN
LIKE -- 模拟匹配
REGEXP -- 判断是否符合正则
RLIKE -- 判断值是否符合正则
SELECT emp_id,comm_id FROM tb_name WHERE col_value IS NULL;
SELECT emp_id,comm_id FROM tb_name WHERE col_value com <=> NULL;
SELECT emp_id,comm_id FROM tb_name WHERE ISNULL(col_value);
SELECT emp_id,comm_id FROM tb_name WHERE col_value = NULL;
SELECT
#查询commission_pct不等于NULL
SELECT employee_id,commission_pct FROM employees WHERE commission_pct IS NOT NULL;
SELECT employee_id,commission_pct FROM employees WHERE NOT commission_pct <=> NULL;
SELECT employee_id,commission_pct FROM employees WHERE NOT ISNULL(commission_pct);
-- minVal
SELECT LEAST (1.0,3),l, LEAST('B','a','c'), LEAST(1,NULL,2);
-- 由结果可以看到,当参数是整数或者浮点数时,LEAST将返回其中最小的值;当参数为字符串时,返回字母表中顺序最靠前的字符;当比较值列表中有NULL时,不能判断大小,返回值为NULL。
--maxVal
SELECT LEAST (1.0,3),l, LEAST('B','a','c'), LEAST(1,NULL,2);
-- 那肯定和上面一样
--BETWEEN AND
SELECT salary,emp_id FROM tb_name
WHERE salary BETWEEN 2500 AND 3500;
-- IN
-- IN运算符用于判断给定的值是否是IN列表中的一个值,如果是则返回1,否则返回0。如果给定的值为NULL,或者IN列表中存在NULL,则结果为NULL。
SELECT emp_id,last_name,manager_id;
FRPM emp_tbale WHERE manager_id IN (100,200,201);
-- NOT IN
运算符用于判断给定的值是否不是IN列表中的一个值,如果不是IN列表中的一个值,则返回1,否则返回0。
-- LIKE运算符
SELECT first_name FROM emp_table WHERE first_name LIKE '%fhakj'
SELECT first_name FROM emp_table WHERE first_name LIKE '_A_'
-- 这里%占位符表示多个字符,_占位表示一个字符
-- NULL LIKE 'abc' 和 'abc' LIKE NULL的值都是NULL
-- ESCAPE
-- 用来自定义转义字符
SELECT job_id FROM job_table WHERE job_id LIKE 'IT\_%' ESCAP '\'
--我们用escape来自定义转义字符,也可使用其他字符
-- REGEXP 正则表达式
WHERE phone REGEXP '^[0-9]{11}$';
-- 逻辑运算符
NOT 或 !
-- NOT NULL 还是 NULL
AND &&
--
OR ||
--
XOR
-- 位运算符号,这些太阴间了,我感觉用不到
排序与分页
1
2
3
4
5
6
7
8
9
10
11
12
13
14
ORDER BY id ASC; -- 默认升序
ORDER BY id DESC ;
ORDER BY id1,id2 DESC ;
LIMIT 0,10 ;
LIMIT 10 ;
LIMIT 10,10; -- 11-20条
LIMIT 10 OFFSET 10 -- 8.0新语法,和上面那个一样
SELECT id FROM table_name WHERE id = '' LIMIT 1
-- 我们如果提前知道只需要返回一条记录,就加上这句话,可以不扫描完整个表,提高效率
多表查询
- 等值连接与非等值连接
对于id连接的是等值连接 对于评定工资等级,用的是between,非等值连接
- 自连接 非自连接
- 内连接 与 外连接
内连接就是,合并多个表,只有有相对应数据的行合并,对应不上的不要 而外连接就恰恰相反,没对应上的我用NULl替代
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
-- sql中大多采用笛卡尔积,但这在很多时候并不是有效的
-- 所以我们使用 WHERE 关键字加入有效的连接条件
SELECT * FROM tb_1,tb_2
WHERE tb_1.id = tb_2.id ;
SELECT employees.last_name, departments.department_name,employees.department_id
FROM employees, departments
WHERE employees.department_id = departments.department_id;
-- 使用别名简化
SELECT e.employee_id, e.last_name, e.department_id,
d.department_id, d.location_id
FROM employees e , departments d
WHERE e.department_id = d.department_id;
-- 需要注意的是,如果我们使用了表的别名,在查询字段中、过滤条件中就只能使用别名进行代替,不能使用原有的表名,否则就会报错。
SELECT CONCAT(worker.last_name ,' works for '
, manager.last_name)
FROM employees worker, employees manager
WHERE worker.manager_id = manager.employee_id ;
JOIN
INNER JOIN
CROSS JOIN
--都是内连接
-- 一般使用 JOIN 和 ON 进行内连接
SELECT e.id,e.lm,e.id2,d.id
FROM table_e e JOIN table_d d
ON (e.id = d.id )
-- 多级
SELECT employee_id, city, department_name
FROM employees e
JOIN departments d
ON d.department_id = e.department_id
JOIN locations l
ON d.location_id = l.location_id;
-- 外连接
LEFT OUTER JOIN;
RIGHT OUTER JOIN;
FULL OUTER JOIN;
FULL JOIN; --Mysql不支持,但是可以用:
LEFT JOIN UNION RIGHT JOIN;
-- 直观地说,右连接就是留下第二个表的所有行,第一个表向它看齐
SELECT e.last_name, e.department_id, d.department_name
FROM employees e
RIGHT OUTER JOIN departments d
ON (e.department_id = d.department_id) ;
-- NUION 合并查询
UNION; -- 合并,去重
UNION ALL ; -- 不去重
SELECT * FROM employees WHERE email LIKE '%a%'
UNION
SELECT * FROM employees WHERE department_id>90;
-- SQL JOINS 集合论说是

1
2
3
4
5
6
7
8
-- NATURAL JOIN : 自然连接
SELECT employee_id,last_name,department_name
FROM employees e NATURAL JOIN departments d;
-- USING连接
SELECT employee_id,last_name,department_name
FROM employees e JOIN departments d
USING (department_id);
单行函数
| 函数 | 用法 | | ——————- | ———————————————————— | | ABS(x) | 返回x的绝对值 | | SIGN(X) | 返回X的符号。正数返回1,负数返回-1,0返回0 | | PI() | 返回圆周率的值 | | CEIL(x),CEILING(x) | 返回大于或等于某个值的最小整数 | | FLOOR(x) | 返回小于或等于某个值的最大整数 | | LEAST(e1,e2,e3…) | 返回列表中的最小值 | | GREATEST(e1,e2,e3…) | 返回列表中的最大值 | | MOD(x,y) | 返回X除以Y后的余数 | | RAND() | 返回0~1的随机值 | | RAND(x) | 返回0~1的随机值,其中x的值用作种子值,相同的X值会产生相同的随机数 | | ROUND(x) | 返回一个对x的值进行四舍五入后,最接近于X的整数 | | ROUND(x,y) | 返回一个对x的值进行四舍五入后最接近X的值,并保留到小数点后面Y位 | | TRUNCATE(x,y) | 返回数字x截断为y位小数的结果 | | SQRT(x) | 返回x的平方根。当X的值为负数时,返回NULL |
| 函数 | 用法 |
|---|---|
| RADIANS(x) | 将角度转化为弧度,其中,参数x为角度值 |
| DEGREES(x) | 将弧度转化为角度,其中,参数x为弧度值 |
| 函数 | 用法 |
|---|---|
| SIN(x) | 返回x的正弦值,其中,参数x为弧度值 |
| ASIN(x) | 返回x的反正弦值,即获取正弦为x的值。如果x的值不在-1到1之间,则返回NULL |
| COS(x) | 返回x的余弦值,其中,参数x为弧度值 |
| ACOS(x) | 返回x的反余弦值,即获取余弦为x的值。如果x的值不在-1到1之间,则返回NULL |
| TAN(x) | 返回x的正切值,其中,参数x为弧度值 |
| ATAN(x) | 返回x的反正切值,即返回正切值为x的值 |
| ATAN2(m,n) | 返回两个参数的反正切值 |
| COT(x) | 返回x的余切值,其中,X为弧度值 |
| 函数 | 用法 | | ——————– | —————————————————- | | POW(x,y),POWER(X,Y) | 返回x的y次方 | | EXP(X) | 返回e的X次方,其中e是一个常数,2.718281828459045 | | LN(X),LOG(X) | 返回以e为底的X的对数,当X <= 0 时,返回的结果为NULL | | LOG10(X) | 返回以10为底的X的对数,当X <= 0 时,返回的结果为NULL | | LOG2(X) | 返回以2为底的X的对数,当X <= 0 时,返回NULL |
SELECT YEAR(CURDATE()),MONTH(CURDATE()),DAY(CURDATE()),
HOUR(CURTIME()),MINUTE(NOW()),SECOND(SYSDATE())
FROM DUAL;
这里东西太多了,我们直接把时间这里跳过了,以后有实际需求再慢慢学
1
2
3
4
5
6
7
8
9
10
11
12
13
14
IF(value1,Tvalue,Fvalue); -- 如果value1为T,返回Tvalue,否则
IFNULL(value1,value2); --value1不为NULL,返回value1,否则
SELECT
employee_id,
department_id,
salary,
CASE department_id
WHEN 10 THEN salary * 1.1
WHEN 20 THEN salary * 1.2
WHEN 30 THEN salary * 1.3
ELSE salary
END AS adjusted_salary
FROM employee_table;
1
2
3
4
5
6
7
8
9
//函数加密
PASSWORD(str);
MD5(str);
SHA(str);
-- 下面的函数已经废弃了,这什么傻鸟教程
ENCODE(value,password_seed) -- 返回使用password_seed作为加密密码加密
valueDECODE(value,password_seed) -- 返回使用password_seed作为加密密码解密value
函数这一节学的有点头疼,主要还是api过多。
聚合函数
- AVG()
- SUM()
- MAX()
- MIN()
- COUNT()
1
2
COUNT(*) --会统计值为NULL的行
COUNT(列名) -- 不会统计列为NULL的值
- GROUP BY ``` sql SELECT department_id, AVG(salary) FROM employees GROUP BY department_id ;
SELECT department_id,AVG(salary) FROM employees WHERE department_id > 80 GROUP BY department_id WITH ROLLUP;
SELECT department_id, MAX(salary) FROM employees GROUP BY department_id HAVING MAX(salary)>10000 ; – 使用GROUP BY之后就要使用HAVING进行过滤, – 禁止 在WHERE中使用GROUP BY !!!
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
``` sql
#方式1:
SELECT ...,....,...
FROM ...,...,....
WHERE 多表的连接条件
AND 不包含组函数的过滤条件
GROUP BY ...,...
HAVING 包含组函数的过滤条件
ORDER BY ... ASC/DESC
LIMIT ...,...
#方式2:
SELECT ...,....,...
FROM ... JOIN ...
ON 多表的连接条件
JOIN ...
ON ...
WHERE 不包含组函数的过滤条件
AND/OR 不包含组函数的过滤条件
GROUP BY ...,...
HAVING 包含组函数的过滤条件
ORDER BY ... ASC/DESC
LIMIT ...,...
#其中:
#(1)from:从哪些表中筛选
#(2)on:关联多表查询时,去除笛卡尔积
#(3)where:从表中筛选的条件
#(4)group by:分组依据
#(5)having:在统计结果中再次筛选
#(6)order by:排序
#(7)limit:分页
子查询
从本章开始,不记忆那么多的api,而把时间专注在如何实现 ``` sql SELECT last_name,salary FROM employees WHERE salary > ( SELECT salary FROM employees WHERE last_name = ‘Abel’ );
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
// 这里内容挺多的,主要还是api
#### 创建和管理表
| 类型 | 类型举例 |
| ---------------- | ------------------------------------------------------------ |
| 整数类型 | TINYINT、SMALLINT、MEDIUMINT、**INT(或INTEGER)**、BIGINT |
| 浮点类型 | FLOAT、DOUBLE |
| 定点数类型 | **DECIMAL** |
| 位类型 | BIT |
| 日期时间类型 | YEAR、TIME、**DATE**、DATETIME、TIMESTAMP |
| 文本字符串类型 | CHAR、**VARCHAR**、TINYTEXT、TEXT、MEDIUMTEXT、LONGTEXT |
| 枚举类型 | ENUM |
| 集合类型 | SET |
| 二进制字符串类型 | BINARY、VARBINARY、TINYBLOB、BLOB、MEDIUMBLOB、LONGBLOB |
| JSON类型 | JSON对象、JSON数组 |
| 空间数据类型 | 单值:GEOMETRY、POINT、LINESTRING、POLYGON;<br/>集合:MULTIPOINT、MULTILINESTRING、MULTIPOLYGON、GEOMETRYCOLLECTION |
其中,常用的几类类型介绍如下:
| 数据类型 | 描述 |
| ------------- | ------------------------------------------------------------ |
| INT | 从-2^31到2^31-1的整型数据。存储大小为 4个字节 |
| CHAR(size) | 定长字符数据。若未指定,默认为1个字符,最大长度255 |
| VARCHAR(size) | 可变长字符数据,根据字符串实际长度保存,**必须指定长度** |
| FLOAT(M,D) | 单精度,占用4个字节,M=整数位+小数位,D=小数位。 D<=M<=255,0<=D<=30,默认M+D<=6 |
| DOUBLE(M,D) | 双精度,占用8个字节,D<=M<=255,0<=D<=30,默认M+D<=15 |
| DECIMAL(M,D) | 高精度小数,占用M+2个字节,D<=M<=65,0<=D<=30,最大取值范围与DOUBLE相同。 |
| DATE | 日期型数据,格式'YYYY-MM-DD' |
| BLOB | 二进制形式的长文本数据,最大可达4G |
| TEXT | 长文本数据,最大可达4G |
``` sql
CREATE DATABASE db_name;
CREATE DATABASE IF NOT EXISTS db_name
CHARACTER SET 字符集;
SHOW DATABASES ;
SELECT DATABASE();
ALTER DATABASE 数据库名 CHARACTER SET 字符集; #比如:gbk、utf8等
DROP DATABASE IF EXISTS 数据库名;
CREATE TABLE [IF NOT EXISTS] 表名(
字段1, 数据类型 [约束条件] [默认值],
字段2, 数据类型 [约束条件] [默认值],
字段3, 数据类型 [约束条件] [默认值],
……
[表约束条件]
);
DESC emp; -- 显示创建表的语句
CREATE TABLE emp1 AS SELECT * FROM employees;
SHOW CREATE TABLE 表名\G;
ALTER TABLE 表名 ADD 【COLUMN】 字段名 字段类型 【FIRST|AFTER 字段名】;
ALTER TABLE 表名 MODIFY 【COLUMN】 字段名1 字段类型 【DEFAULT 默认值】【FIRST|AFTER 字段名2】;
ALTER TABLE 表名 CHANGE 【column】 列名 新列名 新数据类型;
ALTER TABLE tb_name DROP COLUMN col_name
-- 重命名表
RENAME TABLE tb_name TO new_tb_name;
ALTER TABLE tb_name REANME TO new_tb_name
--删除表
DROP TABLE [IF EXISTS] tb_name
-- 清空表
TRUNCATE TABLE tb_name; --使用这条语句不能进行回滚,但DELETE可以回滚
在MySQL 8.0版本中,InnoDB表的DDL支持事务完整性,即DDL操作要么成功要么回滚。DDL操作回滚日志写入到data dictionary数据字典表mysql.innodb_ddl_log(该表是隐藏的表,通过show tables无法看到)中,用于回滚操作。通过设置参数,可将DDL操作日志打印输出到MySQL错误日志中。
数据处理之增删改
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
-- 增
INSERT INTO tb_name
VALUES (v1,v2,v3);
INSERT INTO tb_name(field1)
VALUES (value1)
INSERT INTO sales_reps(id, name, salary, commission_pct)
SELECT employee_id, last_name, salary, commission_pct
FROM employees
WHERE job_id LIKE '%REP%';
-- 改
UPDATE tb_name
SET field1 = value1, field2 = value2
WHERE id=id -- 不加WHERE就可以死了
-- 删
DELETE FROM departments
WHERE department_name = 'Finance';
-- 计算列
CREATE TABLE tb1(
id INT,
a INT,
b INT,
c INT GENERATED ALWAYS AS (a + b) VIRTUAL
);