SQL是一种标准
SQL语言在功能上主要分为如下3大类:
DDL(Data Definition Languages、数据定义语言)
DML(Data Manipulation Language、数据操作语言)
DCL(Data Control Language、数据控制语言)
因为查询语句使用的非常的频繁,所以很多人把查询语句单拎出来一类:DQL(数据查询语言)
还有单独将 COMMIT 、 ROLLBACK 取出来称为TCL (Transaction Control Language,事务控制语言)。
SQL大小写规范 (建议遵守)
命名规则(暂时了解)
阿里巴巴《Java开发手册》之MySQL字段命名
mysql> source d:\mysqldb.sql
使用DESCRIBE 或 DESC 命令,表示表结构
DESCRIBE employees;
--或
DESC employees;
+----------------+-------------+------+-----+---------+-------+
| Field | Type | Null | Key | Default | Extra |
+----------------+-------------+------+-----+---------+-------+
| employee_id | int(6) | NO | PRI | 0 | |
| first_name | varchar(20) | YES | | NULL | |
| last_name | varchar(25) | NO | | NULL | |
| email | varchar(25) | NO | UNI | NULL | |
| phone_number | varchar(20) | YES | | NULL | |
| hire_date | date | NO | | NULL | |
| job_id | varchar(10) | NO | MUL | NULL | |
| salary | double(8,2) | YES | | NULL | |
| commission_pct | double(2,2) | YES | | NULL | |
| manager_id | int(6) | YES | MUL | NULL | |
| department_id | int(4) | YES | MUL | NULL | |
+----------------+-------------+------+-----+---------+-------+
其中,各个字段的含义分别解释如下:
SELECT 1; #没有任何子句
SELECT 9/2; #没有任何子句
语法
SELECT 标识选择哪些列
FROM 标识从哪个表中选择
选择全部列
SELECT * FROM departments;
一般情况下,除非需要使用表中所有的字段数据,最好不要使用通配符‘*’。使用通配符虽然可以节省输入查询语句的时间,但是获取不需要的列数据通常会降低查询和所使用的应用程序的效率。通配符的优势是,当不知道所需要的列的名称时,可以通过它获取它们。在生产环境下,不推荐你直接使用 SELECT * 进行查询。
选择特定的列
SELECT department_id, location_id FROM departments;
MySQL中的SQL语句是不区分大小写的,因此SELECT和select的作用是相同的,但是,许多开发人员习惯将关键字大写、
数据列和表名小写
,读者也应该养成一个良好的编程习惯,这样写出来的代码更容易阅读和维护。
SELECT department_id AS id, department_name NAME FROM departments;
SELECT department_id AS "部门ID", department_name "部门名称" FROM departments;
SELECT department_id FROM employees;
SELECT DISTINCT department_id FROM employees;
SELECT DISTINCT department_id,salary
FROM employees;
所有运算符或列值遇到null值,运算的结果都为null
SELECT employee_id,salary,commission_pct,12 * salary * (1 + commission_pct) "annual_sal"
FROM employees;
这里你一定要注意,在 MySQL 里面, 空值不等于空字符串。一个空字符串的长度是 0,而一个空值的长度是空。而且,在 MySQL 里面,空值是占用空间的
mysql> SELECT * FROM ORDER;
ERROR 1064 (42000): You have an error in your SQL syntax; check the manual that
corresponds to your MySQL server version for the right syntax to use near 'ORDER' at
line 1
SELECT * FROM `order`;
+----------+------------+
| order_id | order_name |
+----------+------------+
| 1 | shkstart |
| 2 | tomcat |
| 3 | dubbo |
+----------+------------+
3 rows in set (0.00 sec)
我们需要保证表中的字段、表名等没有和保留字、数据库系统或常用方法冲突。如果真的相同,请在SQL语句中使用一对``(着重号)引起来。
SELECT 查询还可以对常数进行查询。对的,就是在 SELECT 查询结果中增加一列固定的常数列。这列的取值是我们指定的,而不是从数据表中动态取出的。
你可能会问为什么我们还要对常数进行查询呢?SQL 中的 SELECT 语法的确提供了这个功能,一般来说我们只从一个表中查询数据,通常不需要增加一个固定的常数列,但如果我们想整合不同的数据源,用常数列作为这个表的标记,就需要查询常数。
比如说,我们想对 employees 数据表中的员工姓名进行查询,同时增加一列字段 corporation ,这个字段固定值为“尚硅谷”,可以这样写:
SELECT '尚硅谷' as corporation, last_name FROM employees;
语法
SELECT 字段1,字段2
FROM 表名
WHERE 过滤条件
WHERE子句紧随 FROM子句
查询部门ID为90的员工信息(员工ID,员工姓名,部门ID)
SELECT employee_id AS "员工ID", last_name"员工姓名", job_id AS "工作类型", department_id AS 部门ID
FROM employees
WHERE department_id = 90 ;
# 1.查询员工12个月的工资总和,并起别名为ANNUAL SALARY
SELECT 12*salary*(1+IFNULL(commission_pct,0)) AS "ANNUAL SALARY" FROM employees;
# 2.查询employees表中去除重复的job_id以后的数据
SELECT DISTINCT job_id FROM employees;
# 3.查询工资大于12000的员工姓名和工资
SELECT last_name, salary FROM employees WHERE salary > 12000;
# 4.查询员工号为176的员工的姓名和部门号
SELECT last_name, department_id FROM employees WHERE employee_id = 176;
# 5.显示表 departments 的结构,并查询其中的全部数据
DESC departments;
SELECT * FROM departments;
算术运算符主要用于数学运算,其可以连接运算符前后的两个数值或表达式,对数值或表达式进行加(+)、减(-)、乘(*)、除(/)和取模(%)运算
SELECT 100, 100 + 0, 100 - 0, 100 + 50, 100 + 50 -30, 100 + 35.5, 100 - 35.5
FROM DUAL;
+-----+---------+---------+----------+--------------+------------+------------+
| 100 | 100 + 0 | 100 - 0 | 100 + 50 | 100 + 50 -30 | 100 + 35.5 | 100 - 35.5 |
+-----+---------+---------+----------+--------------+------------+------------+
| 100 | 100 | 100 | 150 | 120 | 135.5 | 64.5 |
+-----+---------+---------+----------+--------------+------------+------------+
SELECT 1 + 1, 100 + '1', 100 + 'A',CONCAT(1,101);
1 + 1 100 + '1' 100 + 'A' CONCAT(1,101)
------ --------- --------- ---------------
2 101 100 1101
- 一个整数类型的值对整数进行加法和减法操作,结果还是一个整数;
- 一个整数类型的值对浮点数进行加法和减法操作,结果是一个浮点数;
- 加法和减法的优先级相同,进行先加后减操作与进行先减后加操作的结果是一样的;
- 在Java中,+的左右两边如果有字符串,那么表示字符串的拼接。但是在MySQL中+只表示数值相加。如果遇到非数值类型,先尝试转成数值,如果转失败,就按0计算。(补充:MySQL中字符串拼接要使用字符串函数CONCAT()实现)
- 100+'1’为101 发生了隐式转换
- 100 + ‘A’ =100 ,因为A转换不了为数值,所以为0
SELECT 100 ,100 * 1 , 100 * 1.0 , 100 / 1.0 , 100 / 2 , 100 + 2 * 5 / 2 ,100 /3 , 100 DIV 0;
100 100 * 1 100 * 1.0 100 / 1.0 100 / 2 100 + 2 * 5 / 2 100 /3 100 DIV 0
------ ------- --------- --------- ------- --------------- ------- -----------
100 100 100.0 100.0000 50.0000 105.0000 33.3333 (NULL)
- 一个数乘以整数1和除以整数1后仍得原数;
- 一个数乘以浮点数1和除以浮点数1后变成浮点数,数值与原数相等;
- 一个数除以整数后,不管是否能除尽,结果都为一个浮点数;
- 一个数除以另一个数,除不尽时,结果为一个浮点数,并保留到小数点后4位;
- 乘法和除法的优先级相同,进行先乘后除操作与先除后乘操作,得出的结果相同。
- 在数学运算中,0不能用作除数,在MySQL中,一个数除以0为NULL。
SELECT 12 % 3, 12 MOD 5, -12%5, -12 MOD -5 FROM DUAL;
12 % 3 12 MOD 5 -12%5 -12 mod -5
------ -------- ------ ------------
0 2 -2 -2
比较运算符用来对表达式左边的操作数和右边的操作数进行比较,**比较的结果为真则返回1,比较的结果为假则返回0,其他情况则返回NULL。**比较运算符经常被用来作为SELECT查询语句的条件来使用,返回符合条件的结果记录。
SELECT 1 = 1, 1 = '1', 1 = 0, 'a' = 'a', (5 + 3) = (2 + 6), '' = NULL , NULL =NULL;
1 = 1 1 = '1' 1 = 0 'a' = 'a' (5 + 3) = (2 + 6) '' = NULL NULL =NULL
------ ------- ------ --------- ----------------- --------- ------------
1 1 0 1 1 (NULL) (NULL)
SELECT 1 = 2, 0 = 'abc', 1 = 'abc' FROM dual;
1 = 2 0 = 'abc' 1 = 'abc'
------ --------- -----------
0 1 0
SELECT 1 <=> '1', 1 <=> 0, 'a' <=> 'a', (5 + 3) <=> (2 + 6), '' <=> NULL, NULL<=> NULL FROM dual;
1 <=> '1' 1 <=> 0 'a' <=> 'a' (5 + 3) <=> (2 + 6) '' <=> NULL NULL<=> NULL
--------- ------- ----------- ------------------- ----------- --------------
1 0 1 1 0 1
SELECT 1 <> 1, 1 != 2, 'a' != 'b', (3+4) <> (2+6), 'a' != NULL, NULL <> NULL;
1 <> 1 1 != 2 'a' != 'b' (3+4) <> (2+6) 'a' != NULL NULL <> NULL
------ ------ ---------- -------------- ----------- --------------
0 1 1 1 (NULL) (NULL)
不等于运算符不能判断NULL值。如果两边的值有任意一个为NULL,或两边都为NULL,则结果为NULL。
SELECT NULL IS NULL, ISNULL(NULL), ISNULL('a'), 1 IS NULL;
NULL IS NULL ISNULL(NULL) ISNULL('a') 1 IS NULL
------------ ------------ ----------- -----------
1 1 0 0
#查询commission_pct等于NULL。比较如下的四种写法
SELECT employee_id,commission_pct FROM employees WHERE commission_pct IS NULL;
SELECT employee_id,commission_pct FROM employees WHERE commission_pct <=> NULL;
SELECT employee_id,commission_pct FROM employees WHERE ISNULL(commission_pct);
SELECT employee_id,commission_pct FROM employees WHERE commission_pct = NULL;
SELECT NULL IS NOT NULL, 'a' IS NOT NULL, 1 IS NOT NULL, NULL <> NULL;
NULL IS NOT NULL 'a' IS NOT NULL 1 IS NOT NULL NULL <> NULL
---------------- --------------- ------------- --------------
0 1 1 (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);
SELECT LEAST (1,0,2), LEAST('b','a','c'), LEAST(1,NULL,2);
LEAST (1,0,2) LEAST('b','a','c') LEAST(1,NULL,2)
------------- ------------------ -----------------
0 a (NULL)
SELECT GREATEST(1,0,2), GREATEST('b','a','c'), GREATEST(1,NULL,2);
GREATEST(1,0,2) GREATEST('b','a','c') GREATEST(1,NULL,2)
--------------- --------------------- --------------------
2 c (NULL)
SELECT 1 BETWEEN 0 AND 1, 10 BETWEEN 11 AND 12, 'b' BETWEEN 'a' AND 'c';
1 BETWEEN 0 AND 1 10 BETWEEN 11 AND 12 'b' BETWEEN 'a' AND 'c'
----------------- -------------------- -------------------------
1 0 1
SELECT 'a' IN ('a','b','c'), 1 IN (2,3), NULL IN ('a','b'), 'a' IN ('a', NULL), NULL IN ('a', NULL);
'a' IN ('a','b','c') 1 IN (2,3) NULL IN ('a','b') 'a' IN ('a', NULL) NULL IN ('a', NULL)
-------------------- ---------- ----------------- ------------------ ---------------------
1 0 (NULL) 1 (NULL)
SELECT 'a' NOT IN ('a','b','c'), 1 NOT IN (2,3);
'a' NOT IN ('a','b','c') 1 NOT IN (2,3)
------------------------ ----------------
0 1
LIKE运算符通常使用如下通配符:
“%”:匹配0个或多个字符。
“_”:只能匹配一个字符。
SELECT NULL LIKE 'abc', 'abc' LIKE NULL;
NULL LIKE 'abc' 'abc' LIKE NULL
--------------- -----------------
(NULL) (NULL)
SELECT first_name
FROM employees
WHERE first_name LIKE 'S%';
SELECT last_name
FROM employees
WHERE last_name LIKE '_o%';
ESCAPE
SELECT job_id
FROM jobs
WHERE job_id LIKE ‘IT\_%‘;
SELECT job_id
FROM jobs
WHERE job_id LIKE ‘IT$_%‘ escape ‘$‘;
REGEXP运算符用来匹配字符串,语法格式为: expr REGEXP 匹配条件 。如果expr满足匹配条件,返回 1
SELECT 'shkstart' REGEXP '^s', 'shkstart' REGEXP 't$', 'shkstart' REGEXP 'hk';
'shkstart' REGEXP '^s' 'shkstart' REGEXP 't$' 'shkstart' REGEXP 'hk'
---------------------- ---------------------- ------------------------
1 1 1
SELECT 'atguigu' REGEXP 'gu.gu', 'atguigu' REGEXP '[ab]';
'atguigu' REGEXP 'gu.gu' 'atguigu' REGEXP '[ab]'
------------------------ -------------------------
1 1
(1)‘^’匹配以该字符后面的字符开头的字符串。
(2)‘$’匹配以该字符前面的字符结尾的字符串。
(3)‘.’匹配任何一个单字符。
(4)“[…]”匹配在方括号内的任何字符。例如,“[abc]”匹配“a”或“b”或“c”。为了命名字符的范围,使用一个‘-’。“[a-z]”匹配任何字母, 而“[0-9]”匹配任何数字。
(5)‘’匹配零个或多个在它前面的字符。例如,“x”匹配任何数量的‘x’字符,“[0-9]”匹配任何数量的数字,而“”匹配任何数量的任何字符。
SELECT NOT 1, NOT 0, NOT(1+1), NOT !1, NOT NULL;
NOT 1 NOT 0 NOT(1+1) NOT !1 NOT NULL
------ ------ -------- ------ ----------
0 1 0 1 (NULL)
SELECT 1 AND -1, 0 AND 1, 0 AND NULL, 1 AND NULL;
1 AND -1 0 AND 1 0 AND NULL 1 AND NULL
-------- ------- ---------- ------------
1 0 0 (NULL)
SELECT employee_id, last_name, job_id, salary
FROM employees
WHERE salary >=10000
AND job_id LIKE '%MAN%';
SELECT 1 OR -1, 1 OR 0, 1 OR NULL, 0 || NULL, NULL || NULL;
1 OR -1 1 OR 0 1 OR NULL 0 || NULL NULL || NULL
------- ------ --------- --------- --------------
1 1 1 (NULL) (NULL)
#查询基本薪资不在9000-12000之间的员工编号和基本薪资
SELECT employee_id,salary FROM employees WHERE NOT (salary >= 9000 AND salary <= 12000);
SELECT employee_id,salary FROM employees WHERE salary < 9000 OR salary > 12000;
SELECT employee_id,salary FROM employees WHERE salary NOT BETWEEN 9000 AND 12000;
SELECT employee_id, last_name, job_id, salary FROM employees WHERE salary >= 10000 OR job_id LIKE '%MAN%';
注意:OR可以和AND一起使用,但是在使用时要注意两者的优先级,由于AND的优先级高于OR,因此先对AND两边的操作数进行操作,再与OR中的操作数结合。
SELECT 1 XOR -1 , 1 XOR 0 , 0 XOR 0 , 1 XOR NULL , 1 XOR 1 XOR 1 , 0 XOR 0 XOR 0;
1 XOR -1 1 XOR 0 0 XOR 0 1 XOR NULL 1 XOR 1 XOR 1 0 XOR 0 XOR 0
-------- ------- ------- ---------- ------------- ---------------
0 1 0 (NULL) 1 0
#要么部门id是10或者20,工资小于8000 要么工资大于8000 部门不是10或者20
select last_name,department_id,salary
from employees
where department_id in (10,20) XOR salary > 8000;
# 1.选择工资不在5000到12000的员工的姓名和工资
SELECT t1.`last_name`,t1.`salary`
FROM employees AS t1
where t1.`salary` NOT between 5000 and 12000;
SELECT last_name, salary
FROM employees
WHERE salary < 5000 OR salary > 12000;
# 2.选择在20或50号部门工作的员工姓名和部门号
select t1.`last_name`,t1.`department_id`
FROM employees AS t1
where t1.`department_id` in (20,50);
SELECT last_name, department_id
FROM employees
WHERE department_id = 20 OR department_id = 50;
# 3.选择公司中没有管理者的员工姓名及job_id
select t1.`last_name`, t1.`job_id`
FROM employees AS t1
where t1.`manager_id` is null;
# 4.选择公司中有奖金的员工姓名,工资和奖金级别
select t1.`last_name`,t1.`salary`,t1.`commission_pct`
FROM employees AS t1
where t1.`commission_pct` is not null;
# 5.选择员工姓名的第三个字母是a的员工姓名
select t1.`last_name`
FROM employees AS t1
where t1.`last_name` like '__a%';
# 6.选择姓名中有字母a和k的员工姓名
SELECT last_name
FROM employees
WHERE last_name LIKE '%a%k%' OR last_name LIKE '%k%a%';
SELECT t1.`last_name`
FROM employees AS t1
WHERE t1.`last_name` LIKE '%a%' and t1.`last_name` LIKE '%k%';
# 7.显示出表 employees 表中 first_name 以 'e'结尾的员工信息
SELECT t1.`first_name`
FROM employees AS t1
where t1.`first_name` like '%e';
SELECT employee_id,first_name,last_name
FROM employees
WHERE first_name REGEXP 'e$';
# 8.显示出表 employees 部门编号在 80-100 之间的姓名、工种
select t1.`last_name`,t1.`job_id`
FROM employees AS t1
where t1.`department_id` between 80 and 100
# 9.显示出表 employees 的 manager_id 是 100,101,110 的员工姓名、工资、管理者id
SELECT t1.`last_name`,t1.`salary`,t1.`manager_id`
FROM employees AS t1
where manager_id in (100,101,110);
使用 ORDER BY 子句排序
#按照hire_date升序排序
SELECT last_name, job_id, department_id, hire_date
FROM employees
ORDER BY hire_date ;
#按照hire_date降序排序
SELECT last_name, job_id, department_id, hire_date
FROM employees
ORDER BY hire_date DESC ;
#按照employee_id升序排序
SELECT last_name, job_id, department_id, hire_date
FROM employees
ORDER BY employee_id ;
#按照别名进行排序
SELECT employee_id, last_name, salary*12 annsal
FROM employees
ORDER BY annsal;
SELECT employee_id, last_name, salary*12 annsal
WHERE annsal IS NOT NULL
FROM employees
ORDER BY annsal;
SELECT employee_id, last_name, salary*12 annsal WHERE annsal is not null FROM employees ORDER BY annsal LIMIT 0, 1000错误代码: 1064
You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'FROM employees
ORDER BY annsal LIMIT 0, 1000' at line 3
SELECT t1.employee_id, t1.last_name, t1.salary*12 annsal
FROM employees t1
WHERE t1.employee_id IS NOT NULL
ORDER BY t1.employee_id
#先对department_id升序排序,然后对 salary 降序排序
SELECT last_name, department_id, salary
FROM employees
ORDER BY department_id, salary DESC;
分页原理
MySQL中使用 LIMIT 实现分页
LIMIT [位置偏移量,] 行数
--前10条记录:
SELECT * FROM 表名 LIMIT 0,10;
或者
SELECT * FROM 表名 LIMIT 10;
--第11至20条记录:
SELECT * FROM 表名 LIMIT 10,10;
--第21至30条记录:
SELECT * FROM 表名 LIMIT 20,10;
MySQL 8.0中可以使用“LIMIT 3 OFFSET 4”,意思是获取从第5条记录开始后面的3条记录,和“LIMIT4,3;”返回的结果相同。
SELECT * FROM table
LIMIT(PageNo - 1)*PageSize,PageSize;
在不同的 DBMS 中使用的关键字可能不同。在 MySQL、PostgreSQL、MariaDB 和 SQLite 中使用 LIMIT 关键字,而且需要放到 SELECT 语句的最后面。
如果是 SQL Server 和 Access,需要使用 TOP 关键字,比如:
SELECT TOP 5 name, hp_max FROM heros ORDER BY hp_max DESC
如果是 DB2,使用 FETCH FIRST 5 ROWS ONLY 这样的关键字:
SELECT name, hp_max FROM heros ORDER BY hp_max DESC FETCH FIRST 5 ROWS ONLY
如果是 Oracle,你需要基于 ROWNUM 来统计行数:
SELECT rownum,last_name,salary FROM employees WHERE rownum < 5 ORDER BY salary DESC;
需要说明的是,这条语句是先取出来前 5 条数据行,然后再按照 hp_max 从高到低的顺序进行排序。但这样产生的结果和上述方法的并不一样。我会在后面讲到子查询,你可以使用
SELECT last_name,salary
FROM employees
ORDER BY salary DESC)
WHERE rownum < 10;
#1. 查询员工的姓名和部门号和年薪,按年薪降序,按姓名升序显示
select last_name,salary *12*(1+IFNULL(commission_pct,0)) AS annsal
FROM employees
ORDER BY annsal DESC, last_name ASC;
#2. 选择工资不在 8000 到 17000 的员工的姓名和工资,按工资降序,显示第21到40位置的数据
select last_name,salary
FROM employees
where salary not between 8000 and 17000
order by salary desc
limit 20,20;#第21个,因为从0开始,所以偏移量是20
#3. 查询邮箱中包含 e 的员工信息,并先按邮箱的字节数降序,再按部门号升序
SELECT last_name,salary
FROM employees
WHERE email like '%e%'
order by LENGTH(email) desc,department_id asc;