最初是瑞典的N有SQK AB 公司,1995年开发
2008年被SUN公司收购
2009年 Oracle收购SUN公司,进而MySQL进入Oracle
2016每年,MySQL 8.0问世
开源的、关系型数据库
支持千万级别的数据量存储,大型的数据库
DB:database,看做是数据库文件(类似:.doc、.txt……)
DBMS:数据库管理系统。(类似于word\wps等工具)
MySQL数据库中安装了MySQL DBMS,使用MySQL DBMS来管理和操作DB,使用的是SQL语言
net start MySQL#服务名
net stop MySQL#服务名
mysql -uroot -ppassword
mysql -u root -p
mysql -uroot -p
-u #用户
-p #密码
-P #端口
-h #host IP
## 查看版本信息
mysql -v
mysql --version
-p 与密码之间不可以加空格,别的都行
show variables like ‘character_%’;_
show variables like ‘collation_%’;
# 查看所有的数据库
show databases;
# 创建新的数据库
create database database_name;
# 使用某个数据库
use database_name;
# 查看所有的表
show tables;
show databases; ## 查看所有数据库表
## 使用某个数据库(切换到该数据库下)
use database_name;
## 查看该数据库下所有的表
show tables;
# 插入数据
insert into TABLE_NAME values(1001,'JJ');
# 查看数据
select * from TABLE_NAME;
# 删除数据
delete from TABLE_NAME where id=1001;
# 更新数据
update from TABLE_NAME
SQL-86
,SQL-89
, SQL-92
,SQL-99
等标准。SQL92
和SQL99
,它们分别代表了92年和99年颁布的SQL标准,我们今天使用的 SQL语言依然遵循这些标准。CREATE # 创建 databases / table / index
DROP # 删除表
ALTER # 修改表
RENAME # 重命名
TRUNCATE # 清空表
SELECT也被单独称作是DQL
INSERT # 插入
DELETE # 删除
UPDATE # 更新、修改
SELECT # 查询
COMMIT、ROLLBACK又被称作TCL 事务控制语言
COMMIT # 提交
ROLLBACK # 回滚
SAVEPOINT # 设置保存点
GRANT # 赋予权限
REVOKE # 回收权限
SQL可以写在一行或者多行。为了提高可读性,各子句分行写,必要时使用缩进
;
或/g
或/G
结束在Windows上大小写不敏感,在Linux上大小写敏感
# 单行注释
/*
多行注释
*/
-- 单行注释,--后面必须要加一个空格🈳️
# 在 mysql 命令行中执行
SELECT 1+1,2*3;
# 伪表中查询
SELECT 1+1,2*3 FROM DUAL;
# 查询全部内容
SELECT * FROM employees;
# 查询部分内容
SELECT employee_id,last_name,salary FROM employees;
AS
""
双引号引起来()SELECT employee_id emp_id,salary sary from employees;
SELECT employee_id AS emp_id,salary AS sary from employees;
SELECT employee_id "emp_id",salary "sary" from employees;
# 加上 DISTINCT 去重
SELECT DISTINCT id AS "ID" FROM employees;
空值参与运算无论加减乘除都是nul
SELECT id*1000 "ID",name FROM employees;
是null
的地方参与运算之后还是null
用于区分关键字与表名
SELECT * FROM `ORDER`;
SELECT '尚硅谷',id,name FROM employees;
SELECT '尚硅谷' AS "公司",id,name FROM employees;
DESC employees;
DESCRIBE employees;
WHERE
过滤数据SELECT * FROM t_admin WHERE id=5;
SELECT * FROM employees WHERE name="Mask";
+
、-
、*
、/
+
、-
|隐式运算SELECT 100+'1' FROM DUAL;
SELECT 100+'a' FROM DUAL;
SELECT 100+null FROM DUAL;
结果分别为:101
、100
、null
当数字放在单引号之内做加减乘除的时候会出发隐式运算,所以结果是101
,但是'a'
不是一个数字,无法做转换
*
、/
| 除法默认带小数点SELECT 100,100*1,100*1.0,100/1.0,100/2,100+2*5/2,100/3,100 DIV 0 FROM DUAL;
SQL做除法默认带小数位
SELECT 12%3,12%5,12 MOD -5,-12%5,-12%-5 FROM DUAL;
若是a % b
,则结果是正还是负数与a有关,与b无关
字符串与字符之间做比较,那么也会触发隐式转换
。
运算符 | 内容 | 运算符 | 内容 |
---|---|---|---|
= | 等于 | <=> | 安全等于 |
!= | 不等于 | <> | 不等于 |
< | 小于 | <= | 小于等于 |
> | 大于 | >= | 大于等于 |
SELECT 1=2,1!=2,1<=>2,1<>2,1='1',1='a',0='a' FROM DUAL;
结果:0 1 0 1 1 0 1
SELECT 'a'='a','ab'='ab','a'='b' FROM DUAL;
结果:1 1 0
select 1=NULL,NULL=NULL from DUAL;
结果:
null
null
SELECT * FROM employees WHERE id=null;
❌ 错误的写法 ❌
SELECT * FROM employees WHERE id<=>null;
✅ 正确的写法 ✅ 使用安全等于<=>
✅
运 算 符 | 名 称 | 作 用 | 示 例 |
---|---|---|---|
IS NULL | 为空运算符 | 判断值、字符串或表达式是否为空 | SELECT B FROM TABLE WHERE A IS NULL |
IS NOTNULL | 不为空运算符 | 判断值、祖父穿或表达式是否不为空 | SELECT B FROM TABLE WHERE A IS NOT NULL |
LEAST | 最小运算符 | 在多个值中返回最小值 | SELECT D FROM TABLE WHERE C LEAST(A,B ) |
GREATEST | 最大运算符 | 在多个值中返回最大值 | SELECT D FROM TABLE WHERE C GREATEST(A,B ) |
BETWEEN AND | 两值之间运算符 | 判断一个值是否有在两个值之间 | SELECT D FROM TABLE WHERE C BETWEEN A AND B |
ISNULL | 为空运算符 | 判断一个值、字符串或表达式是否为空 | SELECT B FROM TABLE WHERE ISNULL |
IN | 属于运算符 | 判断一个值是否为列表中的任意一个值 | SELECT D FROM TABLE WHERE C IN (A,B) |
NOT IN | 不属于运算符 | 判断一个值是否不是列表中的任意一个值 | SELECT D FROM TABLE WHERE C NOT IN (A,B) |
LIKE | 模糊匹配运算符 | 判断一个值是否符合模糊匹配规则 | SELECT C FROM TABLE WHERE A LIKE B |
REGEXP | 正则表达式运算符 | 判断一个值是否符合正则表达式的规则 | SELECT C FROM TABLE WHERE A REGEXP B |
RLIKE | 正则表达式运算符 | 判断一个值是否符合正则表达式的规则 | SELECT C FROM TABLE WHERE A RLIKE B |
SELECT * FROM employees WHERE ISNULL(id) AND name IS NOT NULL;
SELECT * FROM employees WHERE id IS NULL AND name IS NOT NULL;
SELECT * FROM employees WHERE id <=> NULL AND name IS NOT NULL;
SELECT LEAST('A','B','C','D','E'),GREATEST('A','B','C','D','E');
# ↑ A E
SELECT LEAST(id,name) FROM employees;
BETWEEN 0 AND 5
的范围是[0,5]
而非 [0,5)或者其他。
SELECT id FROM employees WHERE id BETWEEN 1002 AND 1003;
SELECT id FROM employees WHERE id >= 1002 AND ID <=1003;
SELECT id FROM employees WHERE id IN(1002,1003);
SELECT id FROM employees WHERE id = 1002 OR id = 1003;
SELECT id FROM employees WHERE id NOT IN(1002,1003);
SELECT id FROM employees WHERE id != 1002 OR id != 1003;
SELECT id FROM employees WHERE NOT id = 1002 OR NOT id = 1003;
# Jack Mask
SELECT * FROM employees WHERE name LIKE '%a%';
# 以 a 开头
SELECT * FROM employees WHERE name LIKE 'a%';
# 以 a 结尾
SELECT * FROM employees WHERE name LIKE '%a';
### 包含 a 或者包含 e
SELECT * FROM employees WHERE name LIKE '%a%' AND name LIKE '%c%';
### a 必须在 e 前面
SELECT * FROM employees WHERE name LIKE '%a%e%';
### 查询第二个字符是 a 的名字
SELECT * FROM employees WHERE name LIKE '_a%';
### 查询第二个字符是下划线且第三个字符是 a 的信息 使用转义字符
SELECT * FROM employees WHERE name LIKE '_\_a%';
SELECT * FROM employees WHERE name LIKE '_$_a%' ESCAPE '$';
# ESCAPE 意思是将`$`作为转义字符
%
:0 个或多个字符
_
:一个字符
\
:普通转义字符
关键字ESCAPE
定义转义字符
运算符 | 作用 | 示例 |
---|---|---|
NOT 或 ! | 逻辑非 | SELECT NOT A |
AND 或 && | 逻辑与 | SELECT A AND B; SELECT A && B; |
OR 或 ` | ` | |
XOR | 逻辑异或 | SELECT A XOR B; |
XOR
逻辑异或:只要 A 与 B 一真一假,那么结果就为真,一样则为假
AND
可以与OR
一起参与运算,但是AND
的优先级要高于OR
;
## 先运算 A AND B 与 C AND D,然后再 OR
A AND B OR C AND D;
运算符 | 作 用 | 示 例 |
---|---|---|
& | 按位与 | SELECT A & B |
| | 按位或 | SELECT A | B |
^ | 按位异或 | SELECT A ^ B |
~ | 按位取反 | SELECT ~ B |
>> | 按位右移 | SELECT A >> 2 |
<< | 按位左移 | SELECT A << 2 |
默认升序 (ASC) | DESC 是降序
## DESC 降序排列
SELECT * FROM employees ORDER BY id;
SELECT * FROM employees ORDER BY id DESC;
可以用在 MySQL | PGSQL | MariaDB | SQLite
SELECT * FROM employees LIMIT 0,3;
SELECT * FROM employees ORDER BY id LIMIT 4,3;
笛卡尔积错误,每个数据都跟另一个表里的每一个数据做了组合。
SELECT empid,depname FROM employees,dep WHERE dep.depid = employees.empid;
# 两个表的链接条件
SELECT id,name FROM employees,department WHERE employees.id = department.id;
# 报错 解决方案
SELECT employees.id,department.name FROM employees,department WHERE employees.id = department.id;
从SQL优化的角度出发,建议每个字段前都指明他所在的表
可以在SELECT
和WHERE
中给表去别名。
SELECT emp.id,dep.name
FROM employees emp,department dep
WHERE emp.id = dep.id;
注意,取别名之后要全部都用别名
等值连接 vs 非等值连接 BETWEEN AND
自连接 vs 非自连接
SELECT * FROM employees;
内连接 vs 外连接
# 左外连接
SELECT empid,depname
FROM employees e,dep d
WHERE e.`empid`=d.depid;
# MySQL 不支持的做法 ()
SELECT empid,depname
FROM employees e,dep d
WHERE e.`empid`=d.depid(+);
## SQL99 内连接
SELECT last_name,department_name,city
FROM employees e JOIN department d
ON e.`employee_id` = d.`department_id`
JOIN locations l
ON d.`location_id` = l.`location_id`;
SELECT last_name,department_name,city
FROM employees e LEFT OUTER JOIN department d
ON e.`employee_id` = d.`department_id`
JOIN locations l
ON d.`location_id` = l.`location_id`;
SELECT last_name,department_name,city
FROM employees e RIGHT OUTER JOIN department d
ON e.`employee_id` = d.`department_id`
JOIN locations l
ON d.`location_id` = l.`location_id`;
利用UNION关键字,可以给出多条SELECT语句,并将它们的结果组合成单个结果集。合并时,两个表对应的列数和数据类型必须相同,并且相互对应。各个SELECT语句之间使用UNION或UNION ALL关键宇分隔。
语法格式:
SELECT COLUMN ... FROM table1
UNION(ALL)
SELECT COLUMN ... FROM table12;
SELECT empid,depname
FROM employees e JOIN dep d
WHERE e.`empid`=d.`depid`;
SELECT empid,depname
FROM employees e LEFT JOIN dep d
WHERE e.`empid`=d.`depid`;
SELECT empid,depname
FROM employees e RIGHT JOIN dep d
WHERE e.`empid`=d.`depid`;
SELECT empid,depname
FROM employees e LEFT JOIN dep d
WHERE e.`empid`=d.`depid`;
WHERE d.`depid` IS NULL;
SELECT empid,depname
FROM employees e RIGHT JOIN dep d
WHERE e.`empid`=d.`depid`;
WHERE e.`depid` IS NULL;
SELECT empid,depname
FROM employees e LEFT JOIN dep d
WHERE e.`empid`=d.`depid`
UNION ALL
SELECT empid,depname
FROM employees e RIGHT JOIN dep d
WHERE e.`empid`=d.`depid`;
WHERE e.`depid` IS NULL;
SELECT empid,depname
FROM employees e LEFT JOIN dep d
WHERE e.`empid`=d.`depid`;
WHERE d.`depid` IS NULL
UNION ALL
SELECT empid,depname
FROM employees e RIGHT JOIN dep d
WHERE e.`empid`=d.`depid`;
左中图 UNION ALL 右中图
SELECT empid,depname
FROM employees e LEFT JOIN dep d
WHERE e.`empid`=d.`depid`;
WHERE d.`depid` IS NULL
UNION ALL
SELECT empid,depname
FROM employees e RIGHT JOIN dep d
WHERE e.`empid`=d.`depid`;
WHERE e.`depid` IS NULL;
$QL99 在SQL92 的基础上提供了一些特殊语法,比如 NATURAL JOIN 用来表示自然连接。我们可以把自然连接理解为 SQL92 中的等值连接。它会帮你自动查询两张连接表中 所有相同的字段,然后进行等值连接。
SELECT empid,depname
FROM employees e NATURAL JOIN dep d;
当两个表中字段名字一样的时候,可以直接用 USING( )
SELECT e.id,d.name
FROM employees e JOIN dep d
USING(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 |
SELECT ABS(-5),ABS(4),SIGN(10),SIGN(-10),SIGN(0),FLOOR(32.32),CEIL(32.32),CEILING(-43.32),CEILING(-43.32),CEILING(32.32),FLOOR(-43.32),MOD(12,5) FROM DUAL;
## 5 4 1 -1 0 32 33 -43 -43 33 -44 2
相同的 x 会导致结果相同
SELECT RAND(),RAND(),RAND(0),RAND(0),RAND(10),RAND(10),RAND(-1),RAND(-1);
# 0.11622921760774145 0.1567088152810082 0.15522042769493574 0.15522042769493574 0.6570515219653505 0.6570515219653505 0.9050373219931845 0.9050373219931845
SELECT ROUND(125.555),ROUND(125.49),ROUND(-12.56),ROUND(-12.49),ROUND(123.456,1),ROUND(123.456,2),ROUND(123.456,-1),ROUND(123.456,-2);
# 126 125 -13 -12 123.5 123.46 120 100
SELECT TRUNCATE(123.456,0),TRUNCATE(123.456,1),TRUNCATE(123.456,-1) FROM DUAL;
# 123 123.4 120
SELECT TRUNCATE(ROUND(123.456,2),0) FROM DUAL;
# 123
函数 | 作用 | 备注 |
---|---|---|
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 为弧度值 |
SELECT SIN(5),ACOS(0.6) FROM DUAL;
# -0.9589242746631385 0.9272952180016123
函数 | 用法 | 备注 |
---|---|---|
POW(x,y) POWER(x,y) | 返回 x 的 y 次方 | |
EXP(x) | 返回 e 的 x 次方ex | |
LN(x),LOG(x) | 返回以 e 为底的 x 的对数,当 x≤0 时,返回结果是NULL | |
LOG10(x) | 返回结果以 10 为底的 X 的对数,当 X≤0 是,返回的结果为NULL | |
LOG2(x) | 返回以 2 为底的 x 的对数,当 x≤0 时,返回NULL |
SELECT POW(2,3),POWER(2,4),EXP(2) FROM DUAL;
# 8 16 7.38905609893065
EXP(x) 是ex
mysql> SELECT EXP(2);
+------------------+
| EXP(2) |
+------------------+
| 7.38905609893065 |
+------------------+
1 row in set (0.01 sec)
mysql> SELECT LN(EXP(2));
+------------+
| LN(EXP(2)) |
+------------+
| 2 |
+------------+
函数 | 作用 | 备注 |
---|---|---|
BIN(x) | 返回 x 的二进制 | |
OCT(x) | 返回 x 的八进制 | |
HEX(x) | 返回 x 的十六进制 | |
CONV(x,f1,f2) | 返回 f1 进制变成 f2 进制 |
SELECT BIN(123089471290387402) FROM DUAL;
# 110110101010011010011100011010011110110101010101111001010
SELECT CONV(15,16,8) FROM DUAL;
# 25
函数 | 作用 | 备注 |
---|---|---|
ASCII(s) | 返回字符串 s 中的第一个字符的 ASCII 码值 | |
CHAR_LENGTH(s) | 返回字符串 s 的字符数。作用与 CHARACTER_LENGTH(s)相同 | |
LENGTH(s) | 返回字符串 s 的字节数,和字符集有关 | |
CONCAT(s1,s2…,sn) | 连接 s1,s2…sn为一个字符串 | |
CONCAT_WS(x,s1,s2…,sn) | 同上,但是每个字符串之间要加上 x | |
INSERT(str,idx,len,replacestr) | 将字符串 str 从第 idx 位置开始,len 个字符长的子串替换为字符串 replacestr | |
REPLACE(str,a,b) | 用字符串 b 替换字符串 str 中弄过所有出现的字符串 a | |
UPPER(s) 或 UCASE(s) | 将字符串 s 的所有字母转换成大写字母 | |
LOWER(s) 或 LCASE(s) | 将字符串 s 的所有字母转换成小写字母 | |
LEFT(str,n) | 返回字符串 str 最左边的 n 个字符 | |
RIGHT(str,n) | 返回字符串 str 最右边的 n 个字符 | |
LPAD(str,len,pad) | 字符串总长度为 10,不满的在左侧插入 pad(右对齐) | |
RPAD(str,len,pad) | 字符串总长度为 10,不满的在右侧插入 pad(左对齐) | |
LTRIM(s) | 去除字符串 s 的左侧空格 | |
RTRIM(s) | 去除字符串 s 的右侧空格 | |
TRIM(s) | 去除字符串 s 的首尾空格 | |
TRIM(s1 FROM s) | 去掉字符串 s 开始与结尾的 s1 | |
TRIM(LEADING s1 FROM s) | 去掉字符串 s 开始处的s1 | |
TRIM(TRAILING s1 FROM s) | 去掉字符串 s 结尾处的 s1 | |
REPEAT(str,n) | 返回 str 重复 n 次的结果 | |
SPACE(n) | 返回 n 个空格 | |
STRCMP(s1,s2) | 比较字符串 s1,s2 的 ASCII 码值的大小 | |
SUBSTR(s,index,len) | 返回从字符串 s 的 index 位置其 len 个字符,作用于 SUBSTRING(s,n,len)、MID(s,n,len)相同 | |
LOCATE(substr,str) | 返回字符串 substr 在字符串 str 中首次出现的位置,作用与 POSITION(substr IN str)、INSTR(str,substr)相同,未找到则返回 0 | |
ELT(m,s1,s2,…,sn) | 返回指定位置的字符串,如果m=1,则返回s1,如果m=2,则返回s2,如果m=n,则返回sn | |
FIELD(s,s1,s2,…,sn) | 返回字符串s在字符串列表中第一次出现的位置 | |
FIND_IN_SET(s1,s2) | 返回字符串s1在字符串s2中出现的位置。其中,字符串s2是。一个以逗号分隔的字符串 | |
REVERSE(s) | 返回 s 反转后的字符串 | |
NULLIF(value1,value2) | 比较两个字符串,若是相等则返回 NULL ,否则返回value1 |
SELECT ASCII('abc'),CHAR_LENGTH('hello'),LENGTH('hello'),CHAR_LENGTH('你好'),LENGTH('你好') FROM DUAL;
# 97 5 5 2 6
注意:
你好
的LENGTH
为5,你好
的 CHAR_LENGTH
为21
开始的SELECT TRIM(' hel lo ');
# `hel lo`
SELECT REVERSE('ajksfghdfjuyagesufgkavdcsdekuy');
# yukedscdvakgfusegayujfdhgfskja
函数 | 作用 | 备注 |
---|---|---|
CURDATE() / CURRENT_DATE() | 获取当前日期,包含年、月、日 | |
CURTIME() / CURRENT_TIME() | 获取当前时间,包含时、分、秒 | |
NOW() / SYSDATE() / CURRENT_TIMESTAMP() / LOCALTIME() / LOCALTIMESTAMP() | 返回当前系统日期和时间 | |
UTC_DATE () | 返回UTC(世界标准时间)日期 |
函数 | 作用 | 备注 |
---|---|---|
UNIX_TIMESTAMP() | 以Unix时间戳的形式返回房钱时间。 | SELECT UNIX_TIMESTAMP();–>1661173047 |
UNIX_YIMESTAMP(date) | 将时间date以Unix时间戳的形式返回 | |
FROM_UNIXTIME(timestamp) | 将UNIX时间戳的时间转换为普通格式的时间 |
函数 | 用法 | 备注 |
---|---|---|
YEAR(date) / MONTH(date) / DAY(date) | 返回具体的日期值 | |
HOUR(time) / MINUTE(time) / SECOND(time) | 返回具体的时间值 | |
MONTHNAME(date) | 返回月份:January,… | |
DAYNAME(date) | 返回星期几,注意:周一是0,周二是1…周日是6 | |
QUARTER(date) | 返回日期对应的季节,范围是1~4 | |
WEEK(date),WEEKOFYEAR(date) | 返回一年中的第几周 | |
DAYOFYEAR(date) | 返回日期是一年中的第几天 | |
DAYOFMONTH(date) | 返回日期位于所在月份的第几天 | |
DAYOFWEEK(date) | 返回洲际,注意:周日是1,周一是2…周六是7 |
函数 | ||
---|---|---|
EXTRACT(type FROM date) | 返回指定日期的特定部分,type值返回值的类型 |
Type 类型 | 作用 | Type 类型 | 作用 |
---|---|---|---|
MICROSECOND | 毫秒数 | SECOND | 秒 |
MINUTE | 分钟 | HOUR | 小时 |
DAY | 天 | WEEK | 日期在一年中的第几个星期 |
MONTH | 日期在一年中的第几个月 | QUARTER | 日期在一年中的第几个季度 |
YEAR | 日期的年份 | SECOND_MICROSECOND | 返回秒和毫秒值 |
MINUTE_MICROSECOND | 返回分钟和毫秒值 | MINUTE_SECOND | 返回分钟和秒值 |
HOUR_MICROSECOND | 返回小时和毫秒值 | HOUR_SECOND | 返回小时和秒值 |
HOUR_MINUTE | 返回小时和分钟值 | DAY_MICROSECOND | 返回日期和毫秒值 |
DAY_SECOND | 返回日期和秒值 | DAY_MINUTE | 返回日期和分钟值 |
DAY_HOUR | 返回日期和小时值 | YEAR_MONTH | 返回年和月 |
函数 | 作用 | 备注 |
---|---|---|
TIME_TO_SEC(time) | 将time转化为秒并返回结果值。转化的公式为:小时*3600+分钟*60+秒 | |
SEC_TO_TIME(time) | 将seconds描述转化为包含小时、分钟和秒的时间 |
函数 | 作用 | 备注 |
---|---|---|
DATE_ADD(datetime, INTERVAL expr type), ADDDATE(date,INTERVAL expr type) | 返回与给定日期时间相差INTERVAL时间段的日期时间 | |
DATE_SUB(date,INTERVAL expr type), SUBDATE(date,INTERVAL expr type) | 返回与date相差INTERVAL时间间隔的日斯 |
函数 | 作用 | 备注 |
---|---|---|
DATE_FORMATE(date,fmt) | 按照字符串fmt格式化日期date值 | |
TIME FORMAT(time,fmt) | 按照字符串fmt格式化时间time值 | |
GET_FORMAT(date_type,format_type) | 返回日期字符串的显示格式 | |
STR_TO_DATE(str, fmt) | 按照宇符串fmt对str进行解析,解析为一个日期 |
流程处理函数可以根据不同的条件,执行不同的处理流程,可以在SQL语句中实现不同的条件选择。MysQL中的流程处理函数主要包括IF()、IFNULL()和CASE()西数。
函数 | 作用 | 备注 |
---|---|---|
IF(vaine,value1,value2) | 如果value的值为TRUE,返回value1,否则 返回value2 | |
IFNULL(value1, value2) | 如果value1不为NULL,返回value1,否则返 回value2 | |
CASE WHEN 条件1THEN结果1WHEN 条件2THEN 结果2…ELSE resultn] END | 相当于Java的i.else if…else… | |
CASE expr WHEN 常量值1THEN 值1 WHEN 常量值1THEN 值1… ELSE (En] END | 相当于Java的switch…case. |
SELECT IF(1,2,3),IFNULL(123,456),IFNULL(NULL,456);
# 2 123 456
SELECT name,salary,IF(salary>6000,'高工资','低工资') "DETAILS" FROM employees;
SELECT salary,CASE WHEN salary>=15000 THEN '白骨精'
WHEN salary>=10000 THEN '潜力股'
WHEN salary>=8000 THEN '还不错'
ELSE '小屌丝' END
FROM employees;
SELECT salary,CASE department WHEN 10 THEN salary*1.1
WHEN 20 THEN salary*1.2
WHEN 30 THEN salary*1.3
ELSE salary*1.4 END "Salary"
FROM employees;
在 MySQL8.0中已经弃用
SELECT PASSWORD('MySQL') FROM DUAL;
不可逆的加密方式
SELECT MD5('MySQL'),SHA('MySQL') FROM DUAL;
| 62a004b95946bb97541afa471dcca73a | deaa0c393a6613972aaccbf1fecfdad67aa21e88 |
在 MySQL8.0中已经弃用
函数 | 作用 | 函数 |
---|---|---|
ENCODE(value,password) | 使用password作为加密密码加密value | |
DECODE(value,password) | 使用password作为解密密码解密value |
函数 | 作用 | 备注 |
---|---|---|
VERSION() | 返回当前MySQL版本号 | |
CONNECTION_ID() | 返回当前MySQL服务器连接数 | |
DATABASE() / SCHEMA() | 返回MySQL命令行当前所在的数据库 | |
USER() / CURRENT_USER() / SYSTEM_USER() / SESSION_USER() | 返回链接MySQL的用户名,返回结果为用户@IP | |
CHARSET(value) | 返回字符串value 自变量的字符集 | |
COLLATION(value) | 返回字符串value 的比较规则 |
函数 | 作用 | 备注 |
---|---|---|
FORMAT(value,n) | 返回对数字value 格式化后的数据,n 表示四舍五入后保留到小数点后n 位 | |
CONV(value,from,to) | 将value的值进行不同进制之间的转换 | |
INET_ATON(ipvalue) | 将以点分隔的1P地址转化为一个数字 | |
INET_NTOA(value) | 将数字形式的IP地址转化为以点分隔的1IP地址 | |
BENCHMARK(n, expr) | 将表达式expr重复执行n次。用于测试MySQL处理expr表达式所耗费的时间 | |
CONVERT(value USING char_code) | 将value所使用的字符编码修改为char_code |
我们上一章讲到了 SQL 单行函数。实际上 SQL 函数还有一类,叫做聚合(或緊集、分组) 函数,它是对一组数据进行汇总的函数,输入的是一组数据的集合,输出的是单个值。
函数 | 作用 | 备注 |
---|---|---|
AVG( ) | 求平均值 | AVG = SUM / COUNT |
SUM( ) | 求和 | |
MAX( ) | 求最大值 | 数字、字符串、日期时间类型 |
MIN( ) | 求最小值 | 数字、字符串、日期时间类型 |
COUNT( ) | 统计个数 | 不统计NULL |
COUNT: 常数
*
字段
如果要用COUNT(字段),该选择什么方式
问:在MysQL 中统计数据表的行数,可以使用三种方式: SELECT COUNT()、SELECT COUNT(1) 和 SELECT COUNT(具体宇段),使用这三者之间的查询效率是怎样的?
答:
在 MysQL InnoDB 存储号1擎中,COUNT() 和COUNT(1)都是对所有结果进行 COUNT。如果有 WHERE 子句,则是对所有符合筛选条件的数据行进行统计;如果没有 WHERE 子句,则是对数据表的数据行数进行统计。
因此 COUNT(*)和 COUNT(1) 本质上并没有区别,执行的复杂度都是。(N),也就是采用全表扫描,进行循环+计数的方式进行统计。
如果是MysQL MyISAM
存储引擎,统计数据表的行数只需要 o(1)的复杂度,这是因为每张 MyISAM 的数据表都有一个meta 信息存储了row-count 值,而一致性则由表级锁来保证。因为 InnoDB 支持事务,采用行级锁和 MVCC机制,所以无法像 MyISAM 一样,只维护一个row_count 变量,因此需要采用扫描全表,进行循环+计数的方式来完成统计。
需要注意的是,在实际执行中,COUNT(*)和 COUNT(1) 的执行时间可能略有差别,不过你还是可以把它俩的执
行效率看成是相等的。
另外在InnoDB
引擎中,如果采用 COUNT(*) 和COUNT(1) 来统计数据行数,要尽量采用二级索引。因为主键采的索引是聚族索引,聚筷索引1包含的信息多,明显会大于二级索引(非聚族索引)。对于 COUNT(*)和
COUNT(1)来说,它们不需要查找具体的行,只是统计行数,系统会自动采用占用空间更小的二级索引1来进行统计。
SELECT
中出现的内容一定要出现在GROUP BY
中
声明在 FROM
、 WHERE
后面,ORDER BY
与 LIMIT
前面
## 查询各个部门的平均工资
SELECT AVG(salary)
FROM dep
GROUP BY depid;
## 查询
SELECT depid,jobid,AVG(salary)
FROM departments
GROUP BY depid,jobid;
HAVING
必须声明在GROUP BY
后面
WHERE
与 HAVING
的对比
HAVING
的范围更大,可以用WHERE
的地方一定可以用HAVING
GROUP BY
或聚合函数的地方一定要用HAVING
WHERE
的执行效率要高于HAVING
### 错误的写法
SELECT department_id,MAX(salary)
FROM employees
WHERE MAX(salary>10000)
GROUP BY department_id;
## 如果过滤条件中使用了聚合函数,则必须使用HAVING来替换WHERE
SELECT department-id,MAX(salary)
FROM employees
GROUP BY department_id
HAVING MAX(salary)>10000;
# 查询部门id为10,20,30,40 这四个部门中最高工资比10000高的部门信息
SELECT department_id,MAX(salary)
FROM employees
WHERE depattment_id IN (10,20,30,40)
GROUP BY department_id
HAVING MAX(salary) > 10000;
SQL 92 语法
SELECT ... , ... , ... FROM ... , ... , ... WHERE 夺标的链接条件 AND 不包含聚合函数的过滤条件 GROUP BY ... , ... HAVING 包含聚合函数的过滤条件 ORDER BY ... , ...(ASC / DESC) LIMIT ... , ...
- 1
- 2
- 3
- 4
- 5
- 6
- 7
SQL 99 语法
SELECT ... , ... , ...(存在聚合函数) FROM ... (LEFT / RIGHT) JOIN ... ON 多表的链接条件 (LEFT / RIGHT) JOIN ... ON WHERE 不包含聚合函数的过滤条件 GROUP BY ... , ... HAVING 包含聚合函数的过滤条件 GROUP BY ... , ...(ASC / DESC) LIMIT ... , ...
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
举例: 查询工资比 Jim 高的所有的员工;
方式一 先查一下Jim的工资,再带进去
SELECT salary FROM employees WHERE last_name = 'Jim' SELECT last_name,salary FROM employees WHERE salary > 1100;
- 1
- 2
- 3
- 4
- 5
- 6
- 7
方式二:自连接
SELECT e2.last_name,e2.salary FROM employees e1,employees e2 WHERE e2.`salary` > e1.`salary` AND e1.last_name == 'Jim'
- 1
- 2
- 3
- 4
方式三:子查询
SELECT last_name,salary FROM employees WHERE salary > ( SELECT salary FROM employees WHERE last_name = 'Jim' );
- 1
- 2
- 3
- 4
- 5
- 6
- 7
称谓规范:外查询(主查询)、内查询(子查询)、
## 可读性比较好
SELECT last_name,salary
FROM employees
WHERE salary > (
SELECT salary
FROM employees
WHERE last_name = 'Jim'
);
## 可读性较差
SELECT last_name,salary
FROM employees
WHERE (
SELECT salary
FROM employees
WHERE last_name = 'Jim'
) < salary;
角度1:从内查询返回结果的条目数
角度2:内查询是否被执行多次