## 一、版本差异 | 差异 | 5.7 | 8.X | 备注 | | -------- | --------------------- | ------------------------ | --- | | 字符集 | utf8 | utf8mb4 | | | 字符序 | utf8mb4_general_ci | utf8mb4_0900_ai_ci | | | JDBC驱动名称 | com.mysql.jdbc.driver | com.mysql.cj.jdbc.driver | | ## 二、常用命令及SQL + 导出数据 ```shell 1.整个库 (带gzip 压缩) mysqldump -u 用户名 -p 数据库名 | gzip > 导出的文件名.sql.gz 2.指定表 mysqldump -u 用户名 -p 数据库名 表名1 表名2 > 导出的文件名.sql 3.只导出表结构 mysqldump -u 用户名 -p -d 数据库名 > 导出的文件名.sql 4.导出所有数据库 mysqldump -u 用户名 -p --all-databases > 导出的文件名.sql ``` `注意:在导出大型数据库时,建议使用--quick或--opt选项来避免将整个结果集装入内存` + 导入数据 ```shell 1.导入整个数据库 mysql -u 用户名 -p 数据库名 < 导出的文件名.sql 2.导入指定表 mysql -u 用户名 -p 数据库名 < 导出的文件名.sql 3.在MySQL命令行中导入 mysql> use 数据库名; mysql> source 导出的文件名.sql; ``` + 查看表字段 ```sql desc table show create table xxxx ``` ## 三、常用函数 ### 1.字符串 + 连接 ```sql concat(字段1,符号,字段2) ``` + 截取 ```sql SUBSTR(str, start, length):从字符串的start位置开始,截取length长度的一部分 LEFT(str, length):从字符串左边开始截取length个字符 RIGHT(str, length):从字符串右边开始截取length个字符 SUBSTRING(str, index):从字符串的index位置开始截取 ``` + 替换 ```sql REPLACE(str, from_str, to_str):将字符串中的from_str替换为to_str ``` + 查找 ```sql FIND_IN_SET(search_string, string_list):在字符串列表中查找指定字符串的位置 select find_in_set('云-09-云NCK978','云-09-云NCK978,云-09-云NCK978') from dual;-- 返回1,下标从1开始 ``` + 大小写转换 ```sql UPPER(str):将字符串转换为大写 LOWER(str):将字符串转换为小写 ``` + 长度 ```sql LENGTH(str):获取字符串的长度 ``` + 去除空格 ```sql TRIM(str):去除字符串首尾的空格 LTRIM(str):去除字符串开始处的空格 RTRIM(str):去除字符串结尾处的空格 ``` + 列转行 ```sql group_concat(name separator ',') -- 逗号拼接 ``` ### 2.时间 + 当前日期时间 ```sql now(): 返回当前日期和时间,格式为YYYY-MM-DD HH:MM:SS current_timestamp(): 返回当前日期和时间戳 curtime(): 返回当前时间,格式为HH:MM:SS ``` + 格式化 ```sql DATE_FORMAT(_date_, _format_) 将日期格式化为指定的格式。 TIME_FORMAT(_time_, _format_) 将时间格式化为指定的格式 ``` + 字符串转日期时间 ```sql select str_to_date('2014-04-22 15:47:06','%Y-%m-%d %H:%i:%s') select str_to_date('20170615','%Y%m%d') ``` + 日期时间加减 ```sql select date_add(curdate(),interval 1 day) -- 加1天 select date_add(curdate(),interval -1 day) -- 减1天 select date_add(now(),interval 1 hour) -- 加1小时 SELECT DATE_ADD("2017-06-15 09:34:21", INTERVAL 15 MINUTE) -- 加15分钟 ``` + 时间差计算 ```sql TIMESTAMPDIFF(MINUTE,时间1,时间2) -- 结果为分钟(支持年月日时分秒) ``` + 其他 ```sql extract(unit FROM date): 从日期时间中提取年、月、日、时、分、秒等单元。 -- select extract(second from now()) week(date): 返回日期所在的周数。 weekday(date): 返回日期所在的星期几。 dayofweek(date): 返回日期是星期几(0-6,0为星期天)。 dayofmonth(date): 返回日期是月份中的第几天。 dayofyear(date): 返回日期是年份中的第几天。 monthname(date): 返回日期所在月份的名称。 dayname(date): 返回日期所在星期的名称。 ``` ### 3.数学 + 向上取整 ```sql SELECT CEIL(3.3), CEILING(-3.3); -- 返回 4 和 -3 ``` + 向下取整 ```sql SELECT FLOOR(4.6), FLOOR(-4.6); -- 返回 4 和 -5 ``` + 随机数 ```sql SELECT RAND(), RAND(), RAND(1), RAND(1); -- 返回不同的随机数 ``` + 四舍五入 ```sql -- ROUND(X, [Y]) - 对数字 X 进行四舍五入,保留 Y 位小数。如果省略 Y,则返回整数 SELECT ROUND(10.5), ROUND(3.4, 1); -- 返回 10 和 3.4 ``` ### 4.判断 ```sql if(condition,'1','2') -- 如果condition不为Null,返回1,否则返回2 ifnull(f1,f2) -- 默认返回f1,如果f1为空返回f2 SELECT NVL(salary, 0) AS 收入 FROM employees; -- 如果salary 为null 返回0 ``` ### 5.类型转换 ```sql -- CAST: 用于转换数据类型。 SELECT CAST('123' AS UNSIGNED INTEGER); -- 将字符串转换为无符号整数 SELECT CAST(123 AS CHAR(3)); -- 将整数转换为固定长度的字符串 -- CONVERT: 用于转换数据类型,并在转换失败时返回NULL SELECT CONVERT('123' TO UNSIGNED INTEGER); -- 将字符串转换为无符号整数 SELECT CONVERT(123 TO CHAR(3)); -- 将整数转换为固定长度的字符串 -- FORMAT: 用于将数值转换为字符串,并按照指定格式进行格式化 SELECT FORMAT(123.456, 2); -- 将浮点数格式化为保留两位小数的字符串 ``` ### 6.正则 ```sql -- 匹配 以prod结尾的表 SELECT * FROM information_schema.tables WHERE table_schema REGEXP 'prod$'; ``` ### 7.窗口函数 + ROW_NUMBER() 为数据集中的每一行分配一个唯一的连续整数,通常用于排序 ```sql SELECT name, salary, ROW_NUMBER() OVER (ORDER BY salary DESC) AS 'rank' FROM employees; -- ROW_NUMBER()函数根据salary列降序排序,并为每行分配一个排名。 ``` + RANK() 类似于ROW_NUMBER(),但它会在有重复值时给出相同的排名 ```sql SELECT name, salary, RANK() OVER (ORDER BY salary DESC) AS 'rank' FROM employees; ``` + DENSE_RANK() 函数在排名时不会跳过排名,即使有重复值 ```sql SELECT name, salary, DENSE_RANK() OVER (ORDER BY salary DESC) AS 'rank' FROM employees; ``` + LEAD() 和 LAG() 访问当前行之后或之前的行的数据 ```sql SELECT name, salary, LAG(salary, 1) OVER (ORDER BY salary DESC) AS 'previous_salary', LEAD(salary, 1) OVER (ORDER BY salary DESC) AS 'next_salary' FROM employees; ``` + SUM()、AVG()、MIN()、MAX() 会对排序后的数据集的子集进行计算 ```sql SELECT name, salary, SUM(salary) OVER (ORDER BY salary DESC) AS 'running_total' FROM employees; ``` 示例: 原始数据 ![[Pasted image 20240108170944.png]] + 排名 ```sql -- 1.科目分数排名 select stu_no,course,score,row_number() over (partition by course order by score desc) from tb_score; -- rank会出先相同排名,如果2个并列的第1之后,下一个我想是第3名,则可以使用RANK函数实现 select stu_no,course,score,rank() over (partition by course order by score desc) from tb_score; -- select stu_no,course,score,dense_rank() over (partition by course order by score desc) from tb_score ``` + 排名+分组 NTILE() ```sql -- NTILE函数的作用是对每个分组排名后,再将对应分组分成N个小组 select stu_no,course,score,rank() over (partition by course order by score desc) rn,NTILE(4) over(partition by course order by score desc ) rn_group from tb_score ``` + 取出每组第一名学号 first_value() ```sql select stu_no,course,score,first_value(stu_no) over (partition by course order by score desc),rank() over (partition by course order by score desc) from tb_score ``` + 累加 sum函数对score做累加计算,根据course分组后计算出每组的累加值 ```sql select stu_no,course,score,sum(score) over (partition by course order by score desc) from tb_score; -- 直接展示累加结果 增加 rows between unbounded preceding and unbounded following select stu_no,course,score,sum(score) over (partition by course order by score desc rows between unbounded preceding and unbounded following) from tb_score ``` ## 四、常用SQL + 按时间范围统计,(年月周天) ```sql select count(YEAR(a.io_first) = YEAR(CURDATE()) and MONTH(a.io_first) = MONTH(CURDATE()) and DAY(a.io_first) = DAY(CURDATE()) or null) as 'today', count(YEAR(a.io_first) = YEAR(CURDATE()) and WEEK(a.io_first) = WEEK(CURDATE()) or null) as 'week', count(YEAR(a.io_first) = YEAR(CURDATE()) and MONTH(a.io_first) = MONTH(CURDATE()) or null) as 'month', count(YEAR(a.io_first) = YEAR(CURDATE()) or null) as 'year'from ar_t_vehicle_io a ``` + 时间范围 ```sql -- 今天 YEAR(a.io_first) = YEAR(CURDATE()) and MONTH(a.io_first) = MONTH(CURDATE()) and DAY(a.io_first) = DAY(CURDATE()) -- 本周 YEAR(a.io_first) = YEAR(CURDATE()) and WEEK(a.io_first) = WEEK(CURDATE()) -- 本月 YEAR(a.io_first) = YEAR(CURDATE()) and MONTH(a.io_first) = MONTH(CURDATE()) -- 本年 YEAR(a.io_first) = YEAR(CURDATE()) ``` ## 五、索引 MySQL的索引包括普通索引、唯一性索引、全文索引、单列索引、多列索引和空间索等。 - 从 `功能逻辑` 上说,索引主要有 4 种,分别是普通索引、唯一索引、主键索引、全文索引。 - 按照 `物理实现方式` ,索引可以分为 2 种:聚簇索引和非聚簇索引。 - 按照 `作用字段个数进行划分`,分成单列索引和联合索引。 ### 5.1 普通索引 在创建普通索引时,不附加任何限制条件,只是用于提高查询效率。这类索引可以创建在`任何数据类型`中,其值 是否唯一和非空,要由字段本身的完整性约束条件决定 ### 5.2 唯一索引 在创建唯一性索引时,限制该索引的值必须是唯一的,但允许有 空值。在一张数据表里`可以有多个唯一索引` ### 5.3 主键索引 默认主键,一张表里`最多只有一个主键索引`,不允许重复、空值 ### 5.4 全文索引 全文索引(也称全文检索)是目前`搜索引擎`使用的一种关键技术。它能够利用【`分词技术`】等多种算法智能分析 出文本文字中关键词的频率和重要性,然后按照一定的算法规则智能地筛选出我们想要的搜索结果。全文索引非 常适合大型数据集,对于小的数据集,它的用处比较小。全文索引只能创建在`CHAR、VARCHAR或TEXT`类型及其系列类型的字段上,`查询数据量较大的 字符串类型`的字段时,使用全文索引可以提高查询速度。 全文索引典型的有两种类型:自然语言的全文索引和布尔全文索引 ### 5.5 空间索引 ## 六、事务 ## 七、维护 + 当前在执行SQL ```sql SHOW PROCESSLIST; ``` + 慢SQL ```sql -- 如果慢查询日志被启用,可以查看日志文件来获取 SQL 语句 SHOW VARIABLES LIKE 'slow_query_log'; ``` + 当前事务和锁 ```sql -- 确认有没有锁等待: show status like 'innodb_row_lock%'; select * from information_schema.innodb_trx; ``` ## 八、其他 ### 8.1 全文检索 ### 8.2 GIS ### 8.3 JSON ## 九、常见问题 ### 9.1 字符集 utf8mb4_general_ci 和 utf8mb4_0900_ai_ci 不兼容,关联查询报错,需要保持一致。 ### 9.2 concat 其中一个为Null,结果为Null,需要加ifnull 判断,或者使用concat_ws ```sql concat(a.io_first,'--',a.io_last) -- 修改 ifnull(concat(a.io_first,'--',a.io_last),a.io_first) ```