为了SQL injection来稍微系统地学一下SQL
数字和字符串拼接
纯数字
SELECT 100+200 AS 姓名;
姓名
300
数字+字符转
1.能转数字 就转数字
2.不能转数字 就转化为0
SELECT 100+'200' AS 姓名;
SELECT 100+'abc' AS 姓名;
姓名
300
姓名
100
字符串+字符串
字符串拼接函数 CONCAT
SELECT CONCAT(first_name,last_name) AS 姓名 FROM employees;
如果有内容为 null 则所有返回 null
解决方法:IFNULL(原始,替代)
SELECT CONCAT(first_name,',',last_name,',',job_id,',',IFNULL(commission_pct,0)) AS name FROM employees;
条件查询
语法
SELECT
查询列表
FROM
表名
WHERE
筛选条件
分类:
- 一,按条件表达式筛选
简单条件运算符: > < = != <> >= <= - 二,逻辑表达式筛选
&& || !
and or not - 三,模糊查询
like
between and
in
is null
SELECT * FROM employees WHERE salary>12000 AND salary<20000;
like 一般和通配符搭配
% 任意多的字符 包括0个
_ 代表一个字符
SELECT * FROM employees WHERE commission_pct like '%%';
这个查询语句不返回 null 类型
between and
临界值不能颠倒
SELECT * FROM employees WHERE salary BETWEEN 12000 AND 20000;
in 在XXX里面
SELECT * FROM employees WHERE salary IN (10000,12000,17000);
IS NULL
判断是不是 null
SELECT * FROM employees WHERE commission_pct IS NULL;
排序查询
一般放在查询语句最后(除了limit语句)
order by
SELECT * FROM employees ORDER BY salary desc;
asc升序 desc降序
默认升序
SELECT *,salary*12*(1+IFNULL(commission_pct,0)) 年薪 FROM employees ORDER BY 年薪 DESC;
先按工资升序 后按编号降序
SELECT * from employees ORDER BY salary,employee_id DESC;
函数
- 单行函数
- 字符函数
- 数字函数
- 日期函数
- 其他函数
- 流程控制函数
- 分组函数
- SUM
- AVG
- MAX
- MIN
- COUNT
字符函数
LENGTH()
SELECT LENGTH('张三123');
utf-8 一个汉字占三个字符集
9
CONCAT()
UPPER()
LOWER()
姓大写名小写
SELECT CONCAT(UPPER(last_name),LOWER(first_name)) AS 姓名 FROM employees;
SUBSTR()
下标从1开始
#截取从 开始到最后
SELECT SUBSTR('上课看B站',4);
#截取指定长度 溢出到末尾
SELECT SUBSTR('上课看B站',4,2);
SELECT SUBSTR('上课看B站',4,5);
B站
INSTR()
返回字符串在前面位置 没有返回0
SELECT INSTR('上课看B站','B站');
4
TRIM()
去前后指定字符 默认为空格
SELECT LENGTH(TRIM(' 上课看B站 '));
SELECT LENGTH(TRIM('a' FROM 'aaa上课看B站aaaa'));
长度为13 = 3 * 4 + 1 三个中文 一个英文
13
LPAD()\RPAD()
指定字符左\右填充 指定长度 小于原来的话就截取开头指定个数
SELECT LPAD('上课看B站',10,'*');
SELECT RPAD('上课看B站',10,'*');
*****上课看B站
REPLACE()
替换
SELECT REPLACE('上课看B站','B站','C站');
上课看C站
数学函数
ROUND()
四舍五入
SELECT ROUND(1.5);
2
小数点后保留指定位数
SELECT ROUND(1.455,2);
1.46
CEIL()
向上取整(>= 最大整数)
FLOOR()
向下取整 (<= 最大整数)
TRUNCATE()
截断
SELECT TRUNCATE(1.69999999999,1);
1.6
MOD()
取余数
日期函数
NOW()
返回系统日期加时间
CURDATE()
系统日期 不包括时间
CURTIME()
系统时间 不包含日期
YEAR()
获取年份
SELECT YEAR(hiredate) FROM employees;
STR_TO_DATE()
字符转化成日期 (通过指定的格式)
SELECT STR_TO_DATE('8-27-2001','%m-%d-%Y');
%m %c都代月份
%m 返回 01 02 03类型
%c 返回 1 2 3类型
2001-08-27
DATE_FORMAT()
SELECT DATE_FORMAT('2001-8-27','%m月%d日%Y年');
08月27日2001年
其他函数
SELECT CONCAT(VERSION(),'\n',USER(),'\n',DATABASE());
5.7.30-0ubuntu0.18.04.1
root@192.168.43.38
myemployees
流程控制函数
IF()
三目运算符
SELECT IF(1>2,1,2);
2
CASE
1类switch
2类if …else if…else
SELECT salary,
CASE
WHEN salary>20000 THEN 'A'
WHEN salary>15000 THEN 'B'
WHEN salary>10000 THEN 'C'
ELSE 'D'
END AS 工资级别
FROM employees;
分组函数
可以和 DISTINCT 搭配去重
SELECT SUM(salary),AVG(salary),MAX(salary),MIN(salary),COUNT(salary) FROM employees;
SUM AVG只能处理数值型
MAX MIN可以字符型 字符对比
COUNT任何值 null不计数
count(*) 可用来统计行数
SELECT DATEDIFF(NOW(),'2001-08-27');
害 白活了 6858 天了
6858
分组查询
group by
支持单个字段和多个字段(用逗号分隔 没有前后差别) 排序放在最后
SELECT AVG(salary),department_id
FROM employees
WHERE email LIKE '%a%'
GROUP BY department_id;
分组后筛选
SELECT COUNT(*),department_id
FROM employees
GROUP BY department_id
HAVING COUNT(*)>2;
SELECT AVG(salary) s,department_id,job_id
from employees
WHERE department_id IS NOT NULL
GROUP BY job_id,department_id
HAVING s>10000
ORDER BY s;
连接查询
SELECT name,boyName from beauty,boys;
笛卡尔乘积现象
表1 m行,表2 n行, 总共 m*n 行
原因:没有匹配规则(连接条件)
分类:
- 按年代分类:
- sql92标准(仅支持内连接)
- sql99标准(推荐) 内连接 外连接 (左外,右外) 交叉连接
- 按功能分类
- 内连接
- 等值连接
- 非等值连接
- 自连接
- 外连接
- 左外连接
- 右外连接
- 全外连接
- 交叉连接
- 内连接
等值连接
SELECT name,boyName from beauty,boys
WHERE beauty.boyfriend_id=boys.id;
如果为表起了别名,则查询的字段就不能使用与拿来的表名去限定
SELECT last_name,e.job_id,job_title
FROM employees e,jobs j
WHERE e.job_id=j.job_id;
非等值连接
(可以区间匹配)
.
自连接
本表的查询结果作为查询条件再次查询
SELECT e.employee_id,e.last_name,m.employee_id,m.last_name
FROM employees e,employees m
WHERE e.manager_id=m.employee_id
- sql99语法
- 内连接
select 查询列表
from 表1 别名
inner join 表2 别名
on 连接条件;
- 内连接
特点:
1也可以添加 排序 分组 筛选
2inner可以省略
3筛选条件放在where后面 连接调节放在on后面 提高分离性 便于阅读
4inner join连接和sql92语法中的等值连接效果是一样的 都是多表交集
①内连接
一)等值连接
查询员工名 部门名
SELECT last_name,department_name
FROM employees e
INNER JOIN departments d
ON e.department_id=d.department_id;
查询名字中包含e的员工名和工种名(添加筛选)
SELECT last_name,job_title
FROM employees e
INNER JOIN jobs j
ON e.job_id=j.job_id
WHERE e.last_name LIKE '%e%';
查询部门个数>3的城市名和部门个数(添加分组+筛选)
SELECT city,COUNT(*) 部门个数
FROM departments d
INNER JOIN locations l
ON d.location_id=l.location_id
GROUP BY city
HAVING COUNT(*)>3;
查询哪个部门的员工人数>3的部门名和员工个数,并按个数降序
SELECT COUNT(*) 个数,department_name
FROM employees e
INNER JOIN departments d
ON e.department_id=d.department_id
GROUP BY department_name
HAVING COUNT(*)>3
ORDER BY COUNT(*) DESC;
二)非等值连接
跟92语法一样 就改成 on就行
三)自连接
SELECT e.last_name,m.last_name
FROM employees e
JOIN employees m
ON e.manager_id=m.employee_id
②外连接