文章目录
- 什么是SQL
- SQL 分类
- SQL语言的规则与规范
- 阿里巴巴MySQL命名规范
- 数据导入指令
- 显示表结构 DESC
- 基本的SELECT语句
- SELECT
- SELECT ... FROM
- 列的别名 AS
- 去除重复行 DISTINCT
- 空值参与运算
- 着重号
- 查询常数
- 过滤数据 WHERE
- 练习
- 运算符
- 算术运算符
- 加减符号
- 乘除符号
- 取模符号
- 符号比较运算符
- 等号运算符
- 不等于运算符
- 非符号类型运算符
- 为空运算符
- 不为空运算符
- 最小值运算符LEAST
- 最大值运算符GREATEST
- 区间运算符BETWEEN AND
- 模糊查询运算符LIKE
- 正则表达式运算符REGEXP
- 逻辑运算符
- 逻辑非运算符
- 逻辑与运算符
- 逻辑或运算符
- 逻辑异或运算符XOR
- 练习
- 运算符的优先级
- 排序与分页
- 排序数据
- 排序规则
- 单列排序
- 多列排序
- 分页
- 实现规则
- 拓展
- 练习
什么是SQL
SQL是一种标准
- SQL(Structured Query Language,结构化查询语言)是使用关系模型的数据库应用语言, 与数据直接打交道 ,由 IBM 上世纪70年代开发出来。后由美国国家标准局(ANSI)开始着手制定SQL标准,先后有 SQL-86 , SQL-89 , SQL-92 , SQL-99 等标准。
- SQL 有两个重要的标准,分别是 SQL92 和 SQL99,它们分别代表了 92 年和 99 年颁布的 SQL 标准,我们今天使用的 SQL 语言依然遵循这些标准。
- 不同的数据库生产厂商都支持SQL语句,但都有特有内容。
SQL 分类
SQL语言在功能上主要分为如下3大类:
DDL(Data Definition Languages、数据定义语言)
- 这些语句定义了不同的数据库、表、视图、索引等数据库对象,还可以用来创建、删除、修改数据库和数据表的结构。
- 主要的语句关键字包括 CREATE 、 DROP 、 ALTER 等。
DML(Data Manipulation Language、数据操作语言)
- 用于添加、删除、更新和查询数据库记录,并检查数据完整性。
- 主要的语句关键字包括 INSERT 、 DELETE 、 UPDATE 、 SELECT 等。SELECT是SQL语言的基础,最为重要。
DCL(Data Control Language、数据控制语言)
- 用于定义数据库、表、字段、用户的访问权限和安全级别。
- 主要的语句关键字包括 GRANT 、 REVOKE 、 COMMIT 、 ROLLBACK 、 SAVEPOINT 等。
因为查询语句使用的非常的频繁,所以很多人把查询语句单拎出来一类:DQL(数据查询语言)
还有单独将 COMMIT 、 ROLLBACK 取出来称为TCL (Transaction Control Language,事务控制语言)。
SQL语言的规则与规范
- SQL 可以写在一行或者多行。为了提高可读性,各子句分行写,必要时使用缩进
- 每条命令以 ; 或 \g 或 \G 结束
- 关键字不能被缩写也不能分行
- 关于标点符号
- 必须保证所有的()、单引号、双引号是成对结束的
- 必须使用英文状态下的半角输入方式
- 字符串型和日期时间类型的数据可以使用单引号(’ ')表示列的别名
- 尽量使用双引号(" "),而且不建议省略as
SQL大小写规范 (建议遵守)
- MySQL 在 Windows 环境下是大小写不敏感的
- MySQL 在 Linux 环境下是大小写敏感的
- 数据库名、表名、表的别名、变量名是严格区分大小写的
- 关键字、函数名、列名(或字段名)、列的别名(字段的别名) 是忽略大小写的。
- 推荐采用统一的书写规范:
- 数据库名、表名、表别名、字段名、字段别名等都小写
- SQL 关键字、函数名、绑定变量等都大写
命名规则(暂时了解)
- 数据库、表名不得超过30个字符,变量名限制为29个
- 必须只能包含 A–Z, a–z, 0–9, _共63个字符
- 数据库名、表名、字段名等对象名中间不要包含空格
- 同一个MySQL软件中,数据库不能同名;同一个库中,表不能重名;同一个表中,字段不能重名
- 必须保证你的字段没有和保留字、数据库系统或常用方法冲突。如果坚持使用,请在SQL语句中使用**``** (着重号)引起来
- 保持字段名和类型的一致性,在命名字段并为其指定数据类型的时候一定要保证一致性。假如数据类型在一个表里是整数,那在另一个表里可就别变成字符型了
阿里巴巴MySQL命名规范
阿里巴巴《Java开发手册》之MySQL字段命名
- 【 强制 】表名、字段名必须使用小写字母或数字,禁止出现数字开头,禁止两个下划线中间只出现数字。数据库字段名的修改代价很大,因为无法进行预发布,所以字段名称需要慎重考虑。
- 正例:aliyun_admin,rdc_config,level3_name
- 反例:AliyunAdmin,rdcConfig,level_3_name
- 【 强制 】禁用保留字,如 desc、range、match、delayed 等,请参考 MySQL 官方保留字。
- 【 强制 】表必备三字段:id, gmt_create, gmt_modified。
- 说明:其中 id 必为主键,类型为BIGINT UNSIGNED、单表时自增、步长为 1。gmt_create,gmt_modified 的类型均为 DATETIME 类型,前者现在时表示主动式创建,后者过去分词表示被动式更新
- 【 推荐 】表的命名最好是遵循 “业务名称_表的作用”。
- 正例:alipay_task 、 force_project、 trade_config
- 【 推荐 】库名与应用名称尽量一致。
- 【参考】合适的字符存储长度,不但节约数据库表空间、节约索引存储,更重要的是提升检索速度。
- 正例:无符号值可以避免误存负数,且扩大了表示范围。
数据导入指令
mysql> source d:\mysqldb.sql
- 或者通过图形化管理工具进行执行SQL脚本
显示表结构 DESC
使用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 | |
+----------------+-------------+------+-----+---------+-------+
其中,各个字段的含义分别解释如下:
- Field:表示字段名称。
- Type:表示字段类型
- Null:表示该列是否可以存储NULL值。
- Key:表示该列是否已编制索引。PRI表示该列是表主键的一部分;UNI表示该列是UNIQUE索引的一部分;MUL表示在列中某个给定值允许出现多次。
- Default:表示该列是否有默认值,如果有,那么值是多少。
- Extra:表示可以获取的与给定列有关的附加信息,例如AUTO_INCREMENT等。
基本的SELECT语句
SELECT
SELECT 1; #没有任何子句
SELECT 9/2; #没有任何子句
SELECT … FROM
语法
SELECT 标识选择哪些列
FROM 标识从哪个表中选择
选择全部列
SELECT * FROM departments;
一般情况下,除非需要使用表中所有的字段数据,最好不要使用通配符‘*’。使用通配符虽然可以节省输入查询语句的时间,但是获取不需要的列数据通常会降低查询和所使用的应用程序的效率。通配符的优势是,当不知道所需要的列的名称时,可以通过它获取它们。在生产环境下,不推荐你直接使用 SELECT * 进行查询。
选择特定的列
SELECT department_id, location_id FROM departments;
MySQL中的SQL语句是不区分大小写的,因此SELECT和select的作用是相同的,但是,许多开发人员习惯将关键字大写、
数据列和表名小写
,读者也应该养成一个良好的编程习惯,这样写出来的代码更容易阅读和维护。
列的别名 AS
- 重命名一个列
- 紧跟列名,也可以在列名和别名之间加入关键字AS,别名使用双引号,以便在别名中包含空格或特殊的字符并区分大小写。
SELECT department_id AS id, department_name NAME FROM departments;
- AS 可以省略
SELECT department_id AS "部门ID", department_name "部门名称" FROM departments;
- 紧跟列名,也可以在列名和别名之间加入关键字AS,别名使用双引号,以便在别名中包含空格或特殊的字符并区分大小写。
去除重复行 DISTINCT
SELECT department_id FROM employees;
SELECT DISTINCT department_id FROM employees;
- 默认情况下,查询会返回全部行,包括重复行。
- 在SELECT语句中使用关键字DISTINCT去除重复行
SELECT DISTINCT department_id,salary
FROM employees;
- SELECT DISTINCT 列名称1,列名称2…组合属性去重,就是这几个列完全一模一样才算重复元素
- SELECT 列名称1,DISTINCT 列名称2则会报错
空值参与运算
所有运算符或列值遇到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;
过滤数据 WHERE
语法
SELECT 字段1,字段2
FROM 表名
WHERE 过滤条件
- 使用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
- 等号运算符(=)判断等号两边的值、字符串或表达式是否相等,如果相等则返回1,不相等则返回0。
- 在使用等号运算符时,遵循如下规则:
- 如果等号两边的值、字符串或表达式都为字符串,则MySQL会按照字符串进行比较,其比较的是每个字符串中字符的ANSI编码是否相等。
- 如果等号两边的值都是整数,则MySQL会按照整数来比较两个值的大小。
- 如果等号两边的值一个是整数,另一个是字符串,则MySQL会将字符串转化为数字进行比较。
- 0 = ‘abc’ abc转为数值失败,变成0
- 如果等号两边的值、字符串或表达式中有一个为NULL,则比较结果为NULL。
- 对比:SQL中赋值符号使用 :=
不等于运算符
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)
- 不等于运算符(<>和!=)用于判断两边的数字、字符串或者表达式的值是否不相等,
- 如果不相等则返回1,相等则返回0。
不等于运算符不能判断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;
- 空运算符(IS NULL或者ISNULL)判断一个值是否为NULL,如果为NULL则返回1,否则返回0。
不为空运算符
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);
- 非空运算符(IS NOT NULL)判断一个值是否不为NULL,如果不为NULL则返回1,否则返回0。
最小值运算符LEAST
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)
- 语法格式为:LEAST(值1,值2,…,值n)。其中,“值n”表示参数列表中有n个值。在有两个或多个参数的情况下,返回最小值。
- 由结果可以看到,当参数是整数或者浮点数时,LEAST将返回其中最小的值;当参数为字符串时,返回字母表中顺序最靠前的字符;当比较值列表中有NULL时,不能判断大小,返回值为NULL。
最大值运算符GREATEST
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)
- 语法格式为:GREATEST(值1,值2,…,值n)。其中,n表示参数列表中有n个值。当有两个或多个参数时,返回值为最大值。假如任意一个自变量为NULL,则GREATEST()的返回值为NULL。
区间运算符BETWEEN AND
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
- BETWEEN运算符使用的格式通常为SELECT D FROM TABLE WHERE C BETWEEN AAND B,此时,当C大于或等于A,并且C小于或等于B时,结果为1,否则结果为0。
- BETWEEN …AND… 是闭合区间,是包括两个边界的
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)
- IN运算符用于判断给定的值是否是IN列表中的一个值,如果是则返回1,否则返回0。如果给定的值为NULL,则结果为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
- NOT IN运算符用于判断给定的值是否不是IN列表中的一个值,如果不是IN列表中的一个值,则返回1,否则返回0。
0。如果给定的值或者匹配条件为NULL,则返回结果为NULL。
模糊查询运算符LIKE
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%';
- LIKE运算符主要用来匹配字符串,通常用于模糊匹配,如果满足条件则返回1,否则返回
ESCAPE
SELECT job_id
FROM jobs
WHERE job_id LIKE ‘IT\_%‘;
SELECT job_id
FROM jobs
WHERE job_id LIKE ‘IT$_%‘ escape ‘$‘;
- 回避特殊符号的:使用转义符。例如:将[%]转为[ %]、[]转为[ ],然后再加上[ESCAPE‘$’]即可
- 如果使用\表示转义,要省略ESCAPE。如果不是\,则要加上ESCAPE。
正则表达式运算符REGEXP
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)
- 逻辑非(NOT或!)运算符表示当给定的值为0时返回1;当给定的值为非0值时返回0;当给定的值为NULL时,返回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%';
- 逻辑与(AND或&&)运算符是当给定的所有值均为非0值,并且都不为NULL时,返回1;当给定的一个值或者多个值为0时则返回0;否则返回NULL
逻辑或运算符
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或||)运算符是当给定的值都不为NULL,并且任何一个值为非0值时,则返回1,否则返回0;当一个值为NULL,并且另一个值为非0值时,返回1,否则返回NULL;当两个值都为NULL时,返回NULL。
注意:OR可以和AND一起使用,但是在使用时要注意两者的优先级,由于AND的优先级高于OR,因此先对AND两边的操作数进行操作,再与OR中的操作数结合。
逻辑异或运算符XOR
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;
- 逻辑异或(XOR)运算符是当给定的值中任意一个值为NULL时,则返回NULL;如果两个非NULL的值都是0或者都不等于0时,则返回0;如果一个值为0,另一个值不为0时,则返回1。
练习
# 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 子句排序
- ASC(ascend): 升序,默认是升序
- DESC(descend):降序
- ORDER BY 子句在SELECT语句的结尾
单列排序
#按照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中出现
- ORDER可以使用别名进行排序
- 因为先将数据查出来,才进行排序,所以SELECT中的别名,ORDER中可以识别
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
- WHERE 中不能使用SELECT中的别名,因为先通过WHERE中的条件进行过滤出数据
- WHERE中可以使用FROM中的别名
- 先执行FROM,从哪来数据
- 再执行WHERE进行过滤
- 其次执行SELECT选出数据
- 最后执行ORDER进行排序
- WHERE要在FROM后面,ORDER在WHERE后面
多列排序
#先对department_id升序排序,然后对 salary 降序排序
SELECT last_name, department_id, salary
FROM employees
ORDER BY department_id, salary DESC;
- 可以使用不在SELECT列表中的列排序。
- 在对多列进行排序的时候,首先排序的第一列必须有相同的列值,才会对第二列进行排序。如果第一列数据中所有值都是唯一的,将不再对第二列进行排序
分页
实现规则
分页原理
- 所谓分页显示,就是将数据库中的结果集,一段一段显示出来需要的条件。
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;”返回的结果相同。
- 位置偏移量从0开始,并且LIMIT N,M是包括N的
SELECT * FROM table
LIMIT(PageNo - 1)*PageSize,PageSize;
- 注意:LIMIT 子句必须放在整个SELECT语句的最后!
- 使用 LIMIT 的好处
- 约束返回结果的数量可以 减少数据表的网络传输量 ,也可以提升查询效率 。如果我们知道返回结果只有1 条,就可以使用 LIMIT 1 ,告诉 SELECT 语句只需要返回一条记录即可。这样的好处就是 SELECT 不需要扫描完整的表,只需要检索到一条符合条件的记录即可返回
拓展
在不同的 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;