SQL语言学习笔记(3)DQL(Data Query Language):数据查询语言
数据库执行 DQL 语句不会对数据进行改变,而是让数据库发送结果集给客户端。
查询数据是指从数据库中获取所需要的数据。查询数据是数据库操作中最常用,也是最重要的操作。用户可以根据自己对数据的需求,使用不同的查询方式。通过不同的查询方式,可以获得不同的数据。在MySQL中是使用select语句来查询数据的。
1. 基本查询语句
MySQL中,select的基本语法形式如下:
SELECT 字段列表 -- 要查询的列名称列表
FROM 表名 -- 要查询的表名称
[WHERE 条件表达式] -- 行条件
[GROUP BY 字段名1] -- 对结果分组
[HAVING 分组条件] -- 分组后的行条件
[ORDER BY 字段名2 [ ASC | DESC ]] -- 排序
[LIMIT 起始行,行数] -- 结果限定
2. 单表查询
单表查询是指从一张表中查询所需要的数据。查询数据时,可以从一张表中查询数据,也可以从多张表中同时查询数据。两者的查询方式有一定的区别。因为单表查询只在一张表上进行操作,所以查询比较简单。
2.1 查询所有字段
查询所有字段是指查询表中所有字段的数据。这种方式可以将表中所有字段的数据都查询出来。MySQL中使用“*”查询表中所有的字段。其基本语法形式为:
SELECT * FROM 表名;
“*”可以表示所有的字段。这样就不用列出表中所有字段的名称了。但是,使用这种方式查询时,只能按照表中字段的顺序进行排列,不能改变字段的排列顺序。需要指定顺序排列的话,可以使用下面查询指定字段的方法。
2.2 查询指定字段
查询数据时,可以在SELECT语句的“字段列表”中列出所要查询的字段。这种方式可以指定需要查询的字段,而不需要查询出所有的字段。其基本语法形式为:
SELECT 列名1,列名2,列名3,...列名n FROM 表名;
2.3 查询结果不重复
SELECT语句返回所有匹配的行,如果表中的某些字段上没有唯一性约束,这些字段可能存在着重复的值。SELECT语句中可以使用DISTINCT关键字来消除重复的记录。其基本语法形式为:
SELECT DISTINCT 字段名列表 FROM 表名
注意:不能部分使用DISTINCT
DISTINCT关键字作用于所有的列,不仅仅是跟在其后的那一列。
例如
SELECT DISTINCT name, age FROM student
,DISTINCT作用于其后的两列。
2.4 条件查询
条件查询就是在查询时给出 WHERE 子句,其基本语法形式为:
SELECT 字段名列表 FROM 表名 WHERE 条件表达式
2.4.1 带运算符的查询
运算符 | 说明 |
---|---|
= | 等于 |
<> | 不等于 |
!= | 不等于 |
< | 小于 |
<= | 小于等于 |
!< | 不小于 |
> | 大于 |
>= | 大于等于 |
!> | 不大于 |
下面查询employee表中d_id为1001的记录。SELECT语句的代码如下:
SELECT * FROM employee WHERE d_id=1001;
查询employee表中d_id大于等于1001的记录。SELECT语句的代码有两种写法,如下:
SELECT * FROM employee WHERE d_id>=1001;
SELECT * FROM employee WHERE d_id!<1001;
2.4.2 带IN关键字的查询
IN关键字可以判断某个字段的值是否在指定的集合中。如果字段的值在集合中,则满足查询条件,该记录将被查询出来;如果不在集合中,则不满足查询条件。其语法规则如下:
SELECT 字段名列表 FROM 表名 WHERE 字段 [NOT] IN (元素1,元素2,...,元素n)
其中,“NOT”是可选参数,加上NOT表示不在集合内满足条件;“元素n”表示集合中的元素,各元素之间用逗号隔开,字符型元素需要加上单引号。
下面使用in关键字进行查询。SELECT语句的代码如下:
SELECT * FROM emplyee WHERE d_id IN (1001,1004);
2.4.3 带BETWEEN AND的范围查询
BETWEEN AND关键字可以判断某个字段的值是否在指定的范围内。如果字段的值在指定范围内,则满足查询条件,该记录将被查询出来。如果不在指定范围内,则不满足查询条件。其语法规则如下:
SELECT 字段名列表 FROM 表名 WHERE 字段名 [NOT] BETWEEN 取值1 AND 取值2;
其中,“NOT”是可选参数,加上NOT表示不在指定范围内满足条件;“取值1”表示范围的起始值;“取值2”表示范围的终止值。
下面使用BETWEEN AND关键字进行查询,查询条件是age字段的取值从15-25。SELECT语句的代码如下:
SELECT * FROM employee WHERE age BETWEEN 15 AND 25;
2.4.4 带LIKE的字符匹配查询
LIKE关键字可以匹配字符串是否相等。如果字段的值与指定的字符串匹配,则满足查询条件,该记录将被查询出来。如果与指定的字符串不匹配,则不满足查询条件。其语法规则如下:
SELECT 字段名列表 FROM 表名 WHERE 字段名 [NOT] LIKE '字符串'
其中,“NOT”是可选参数,加上NOT表示与指定的字符串不匹配时满足条件;“字符串”表示指定用来匹配的字符串,该字符串必须加单引号或者双引号。“字符串”参数的值可以是一个完整的字符串,也可以是包含百分号(%)或者下划线(_)的通配字符。但是%和_有很大的差别:
- “%”可以代表任意长度的字符串,长度可以为0。例如,b%k表示以字母b开头,以字符k结尾的任意长度的字符串。该字符串可以代表bk、buk、book、break、bedrock等字符串。
- “”只能表示单个字符。例如,b_k表示以字母b开头,以字母k结尾的3个字符。中间的“”可以代表任意一个字符。字符串可以代表bok、bak和buk等字符串。
- “**[ ]”**可以匹配集合内的字符,例如 [ab] 将匹配字符 a 或者 b。用脱字符 ^ 可以对其进行否定,也就是不匹配集合内的字符。
SELECT *
FROM mytable
WHERE col LIKE '[^AB]%'; -- 不以 A 和 B 开头的任意文本
使用通配符的注意事项:
正如所见,SQL的通配符很有用,但这种功能的使用是有代价的,即通配符搜索一般比其他搜索要耗费更长的处理时间。
- 不要过度使用通配符。如果其它操作符能达到相同的目的,应该使用其它操作符
- 在确实需要使用通配符时,也尽量不要把它们用在搜索模式的开始处。把通配符置于开始处,搜索起来是最慢的
2.4.5 查询空值
IS NULL关键字可以用来判断字段的值是否为空值(null)。如果字段的值是空值,则满足查询条件,该记录将被查询出来。如果字段的值不是空值,则不满足查询条件。其语法规则如下:
SELECT 字段名列表 FROM 表名 WHERE 字段名 IS [NOT] NULL
其中,“NOT”是可选参数,加上NOT表示字段不是空值时满足条件。
下面使用IS NULL关键字来查询work表中info字段为空值的记录。SELECT语句的代码如下:
SELECT * FROM work WHERE info IS NULL;
2.4.6 带AND的多条件查询
AND关键字可以用来联合多个条件进行查询。使用AND关键字时,只有同时满足所有查询条件的记录会被查询出来。如果不满足这些查询条件的其中一个,这样的记录将被排除掉。and关键字的语法规则如下:
SELECT 字段名列表
FROM 表名
WHERE 条件表达式1 AND 条件表达式2 [...AND 条件表达式n]
其中,AND可以连接两个条件表达式。而且,可以同时使用多个AND关键字,这样可以连接更多的条件表达式。
下面使用AND关键字来查询employee表中d_id为1001,而且sex为‘男’的记录。SELECT语法的代码如下:
SELECT * FROM employee WHERE d_id = 1001 AND sex = '男';
2.4.7 带OR的多条件查询
OR关键字也可以用来联合多个条件进行查询,但是与AND关键字不同。使用OR关键字时,只要满足这几个查询条件的其中一个,这样的记录将会被查询出来。如果不满足这些查询条件中的任何一个,这样的记录将被排除掉。OR关键字的语法规则如下:
SELECT 字段名列表
FROM 表名
WHERE 条件表达式1 OR 条件表达式2 [...OR 条件表达式n]
其中,OR可以用来连接两个条件表达式。而且,可以同时使用多个OR关键字,这样可以连接更多的条件表达式。
下面使用OR关键字来查询employee表中d_id为1001,或者sex为‘男’的记录。SELECT语句的代码如下:
SELECT * FROM employee WHERE d_id = 1001 OR sex = '男';
2.5 对查询结果排序
从表中查询出来的数据可能是无序的,或者其排序顺序不是用户所期望的顺序。为了使查询结果的顺序满足用户的需求,可以使用ORDER BY关键字对记录进行排序。其语法规则如下:
ORDER BY 字段名1 [ ASC | DESC ] [, 字段名2 [ ASC | DESC ] ]
其中,“字段名”参数表示按照该字段进行排序;
ASC参数表示按升序的顺序进行排序;
DESC参数表示按降序的顺序进行排序。
默认的情况下,按照ASC升序方式进行排序。
下面查询employee表中的所有记录,按照age字段进行排序。带order by关键字的select语句如下:
SELECT * FROM employee ORDER BY age ASC;
注意点:
- ORDER BY子句必须是SELECT语句中最后一条子句。如果它不是最后的子句,将会出错
- 多个列排序时,只须指定多个列名,列名之间用逗号隔开就行。如果想在多个列上进行降序排序,必须为每一列指定DESC关键字
2.6 聚合函数
聚合函数是对某些行运行的函数,计算并返回一个值:
- COUNT():统计指定列不为 NULL 的记录行数;
- MAX():计算指定列的最大值,如果指定列是字符串类型,那么使用字符串排序运算;
- MIN():计算指定列的最小值,如果指定列是字符串类型,那么使用字符串排序运算;
- SUM():计算指定列的数值和,如果指定列类型不是数值类型,那么计算结果为 0;
- AVG():计算指定列的平均值,如果指定列类型不是数值类型,那么计算结果为 0;
2.6.1 COUNT()函数
COUNT()函数进行计数。可利用COUNT()确定表中行的数目或符合特定条件的行的数目。
- 使用COUNT(*)对表中行的数目进行计数,不管表列中包含的是空值(NULL)还是非空值。
- 使用COUNT(列名)对特定列中具有值的行进行计数,忽略NULL值。
举例:
查询 emp 表中记录数:
SELECT COUNT(*) AS cnt FROM emp;
查询 emp 表中有佣金的人数:
SELECT COUNT(comm) cnt FROM emp;
注意,因为 count()函数中给出的是 comm 列,那么只统计 comm 列非 NULL 的行数。
查询 emp 表中月薪大于 2500 的人数:
SELECT COUNT(*) FROM emp WHERE sal > 2500;
统计月薪与佣金之和大于 2500 元的人数:
SELECT COUNT(*) AS cnt FROM emp WHERE sal+IFNULL(comm,0) > 2500;
查询有佣金的人数,以及有领导的人数:
SELECT COUNT(comm), COUNT(mgr) FROM emp;
2.6.2 SUM()函数
SUM()用来返回指定列值的和(总计)。
举例:
查询所有雇员月薪和:
SELECT SUM(sal) FROM emp;
查询所有雇员月薪和,以及所有雇员佣金和:
SELECT SUM(sal), SUM(comm) FROM emp;
查询所有雇员月薪+佣金和:
SELECT SUM(sal+IFNULL(comm,0)) FROM emp;
2.6.3 AVG()函数
AVG()通过对表中行数计数并计算其列值之和,求得该列的平均值。
AVG()可用来返回所有列的平均值,也可以用来返回特定列或行的平均值。
AVG()函数忽略列值为NULL的行。
举例:
统计所有员工平均工资:
SELECT AVG(sal) FROM emp;
2.6.4 MAX()和 MIN()函数
MAX()返回指定列中的最大值。MAX()要求指定列名。
MIN()返回指定列中的最小值。MIN()要求指定列名。
注意:对非数值数据使用MAX()和 MIN()函数。
虽然MAX()和 MIN()函数一般用来找出最大或最小的数值或日期值,但也可以用于文本数据,会返回该列降序或升序排序后的第一行
举例:
查询最高工资和最低工资:
2.6.5 聚集不同值
SELECT MAX(sal), MIN(sal) FROM emp;
以上五个聚集函数都可以如下使用
- 对所有行执行计算,指定ALL参数或不指定参数(因为ALL是默认行为)
- 只包含不同的值,指定DISTINCT参数
注意:ALL为默认
ALL参数不需要指定,因为它是默认行为。如果不指定DISTINCT,则假定为ALL
举例:
SELECT AVG(DISTINCT prod_price) AS avg_price
FROM products
WHERE vend_id = 'DLL1001'
2.7 分组查询
GROUP BY关键字可以将查询结果按某个字段或多个字段进行分组。字段中值相等的为一组。其语法规则如下:
GROUP BY 属性名 [HAVING 条件表达式] [WITH ROLLUP]
其中,“属性名”是指按照该字段的值进行分组;“HAVING条件表达式”用来限制分组后的显示,满足条件表达式的结果将被显示;WITH ROLLUP关键字将会在所有记录的最后加上一条记录。该记录是上面所有记录的总和。
GROUP BY关键字可以和GROUP_CONCAT()函数一起使用。GROUP_CONCAT()函数会把每个分组中指定字段值都显示出来。同时,GROUP BY关键字通常与集合函数一起使用。集合函数包括COUNT()、SUM()、AVG()、MAX()和MIN()。如果GROUP BY不与上述函数一起使用,那么查询结果就是字段取值的分组情况。字段中取值相同的记录为一组,但只显示该组的第一条记录。
举例:
新建以下数据库
CREATE TABLE test_group (
id INT(10) PRIMARY KEY,
name VARCHAR(5),
age TINYINT(4),
sex CHAR(2),
address Varchar(255)
);
INSERT INTO test_group(id,name,age,sex,address)
VALUES(1,'测试1',1,'男','测试地址1');
INSERT INTO test_group(id,name,age,sex,address)
VALUES(2,'测试2',1,'男','测试地址2');
INSERT INTO test_group(id,name,age,sex,address)
VALUES(3,'测试3',3,'女','测试地址3');
INSERT INTO test_group(id,name,age,sex,address)
VALUES(4,'测试4',42,'男','测试地址4');
INSERT INTO test_group(id,name,age,sex,address)
VALUES(5,'测试5',5,'女','测试地址5');
INSERT INTO test_group(id,name,age,sex,address)
VALUES(6,'测试6',2,'男','测试地址6');
INSERT INTO test_group(id,name,age,sex,address)
VALUES(7,'测试7',7,'女','测试地址7');
2.7.1 单独使用group by关键字来分组
如果单独使用group by关键字,查询结果只显示一个分组的一条记录。
下面按test_group表的sex字段进行分组查询,查询结果与分组前结果进行对比。先执行不带group by关键字的select语句。语句执行如下:
SELECT * FROM test_group ;
结果为:
id|name|age|sex|address|
--+----+---+---+-------+
1|测试1 | 1|男 |测试地址1 |
2|测试2 | 1|男 |测试地址2 |
3|测试3 | 3|女 |测试地址3 |
4|测试4 | 2|男 |测试地址4 |
5|测试5 | 5|女 |测试地址5 |
6|测试6 | 2|男 |测试地址6 |
7|测试7 | 7|女 |测试地址7 |
带有group by关键字的select语句的代码如下:
SELECT * FROM test_group GROUP BY sex;
结果为:
id|name|age|sex|address|
--+----+---+---+-------+
3|测试3 | 3|女 |测试地址3 |
1|测试1 | 1|男 |测试地址1 |
2.7.2 group by关键字与group_concat()函数一起使用
group by关键字与group_concat()函数一起使用时,每个分组中指定字段值都显示出来。
下面按test_group表的sex字段进行分组查询。使用group_concat()函数将每个分组的name字段的值显示出来。select语句的代码如下:
SELECT sex , GROUP_CONCAT(name) FROM test_group GROUP BY sex;
结果为:
sex|GROUP_CONCAT(name)|
---+------------------+
女 |测试3,测试5,测试7 |
男 |测试1,测试2,测试4,测试6 |
2.7.3 group by关键字与集合函数一起使用
group by关键字与集合函数一起使用时,可以通过集合函数计算分组中的总记录、最大值、最小值等。
下面按test_group表的sex字段进行分组查询。sex字段取值相同的为一组。然后对每一组使用集合函数count()进行计算,求出每一组的记录数。select语句的代码如下:
SELECT sex , COUNT(sex) FROM test_group GROUP BY sex;
结果为:
sex|COUNT(sex)|
---+----------+
女 | 3|
男 | 4|
2.7.4 group by关键字与having一起使用
如果加上“Having 条件表达式”,可以限制输出的结果。只有满足条件表达式的结果才会显示。
下面按test_group表的sex字段进行分组查询。然后显示记录数大于等于4的分组。select语句的代码如下:
SELECT sex , COUNT(sex) FROM test_group Group BY sex Having COUNT(sex) >= 4;
结果为:
sex|COUNT(sex)|
---+----------+
男 | 4|
2.7.5 按多个字段进行分组
MySQL中,还可以按多个字段进行分组。例如,employee表按照d_id字段和sex字段进行分组。分组过程中,先按照d_id字段进行分组。遇到d_id字段的值相等的情况时,再把d_id值相等的记录按照sex字段进行分组。
下面test_group表按照age字段和sex字段进行分组。select语句如下:
SELECT * FROM test_group group by age,sex;
结果为
id|name|age|sex|address|
--+----+---+---+-------+
1|测试1 | 1|男 |测试地址1 |
4|测试4 | 2|男 |测试地址4 |
3|测试3 | 3|女 |测试地址3 |
5|测试5 | 5|女 |测试地址5 |
7|测试7 | 7|女 |测试地址7 |
2.7.6 group by关键字与with rollup一起使用
使用with rollup时,将会在所有记录的最后加上一条记录。这条记录是上面所有记录的总和。
下面按test_group表的sex字段进行分组查询。使用count()函数来计算每组的记录数。并且加上with rollup。select语句如下:
SELECT sex , COUNT(sex) FROM test_group GROUP BY sex WITH rollup;
结果为:
2.8 用limt限制查询结果的数量
sex|COUNT(sex)|
---+----------+
女 | 3|
男 | 4|
| 7|
SELECT语句返回指定表中所有匹配的行,很可能是一行。如果你只想返回第一行或者一定数量的行,该怎么办呢?这是可行的,然而遗憾的是,各种数据库中的这一SQL实现并不相同。下面以MYSQL举例。
2.8.1 不指定初始位置
limit关键字不指定初始位置时,记录从第一条记录开始显示。显示记录的条数有limit关键字指定。其语法规则如下:
LIMIT 记录数
其中,“记录数”参数表示显示记录的条数。如果“记录数”的值小于查询结果的总记录数,将会从第一条记录开始,显示指定条数的记录。如果“记录数”的值大于查询结果的总记录数,数据库系统会直接显示查询出来的所有记录。
下面查询employee表的所有记录。但只显示前两条。SELECT语句如下
SELECT * FROM employee LIMIT 2;
2.8.2 指定初始位置
limit关键字可以指定从哪条记录开始显示,并且可以指定显示多少条记录。其语法规则如下:
LIMIT 初始位置,记录数
其中,“初始位置”参数指定从哪条记录开始显示;“记录数”参数表示显示记录的条数。第一条记录的位置是0,第二条记录的位置是1。后面的记录依次类推。
下面查询employee表的所有记录,显示第二条和第三条记录。select语句如下:
select * from employee limit 1,2;
3 连接查询
连接用于连接多个表,使用 JOIN 关键字,并且条件语句使用 ON 而不是 WHERE。
连接可以替换子查询,并且比子查询的效率一般会更快。
可以用 AS 给列名、计算字段和表名取别名,给表名取别名是为了简化 SQL 语句以及连接相同表。
3.1 内连接
内连接查询是一种最常用的连接查询。内连接查询可以查询两个或两个以上的表。为了读者更好的理解,暂时只讲解两个表的连接查询。当两个表中存在表示相同意义的字段时,可以通过该字段来连接这两个表;当该字段的值相等时,就查询出该记录。
内连接又称等值连接,使用 INNER JOIN 关键字。
SELECT A.value, B.value
FROM tablea AS A INNER JOIN tableb AS B
ON A.key = B.key;
可以不明确使用 INNER JOIN,而使用普通查询并在 WHERE 中将两个表中要连接的列用等值方法连接起来。
SELECT A.value, B.value
FROM tablea AS A, tableb AS B
WHERE A.key = B.key;
在没有条件语句的情况下返回笛卡尔积。
3.2 自连接
自连接可以看成内连接的一种,只是连接的表是自身而已。
一张员工表,包含员工姓名和员工所属部门,要找出与 Jim 处在同一部门的所有员工姓名。
子查询版本
SELECT name
FROM employee
WHERE department = (
SELECT department
FROM employee
WHERE name = "Jim");
自连接版本
SELECT e1.name
FROM employee AS e1 INNER JOIN employee AS e2
ON e1.department = e2.department
AND e2.name = "Jim";
3.3 自然连接
自然连接是把同名列通过等值测试连接起来的,同名列可以有多个。
内连接和自然连接的区别: 内连接提供连接的列,而自然连接自动连接所有同名列。
SELECT A.value, B.value
FROM tablea AS A NATURAL JOIN tableb AS B;
3.4 外连接
外连接查询可以查询两个或两个以上的表。外连接查询也需要通过指定字段来进行连接。当该字段取值相等时,可以查询出该记录。而且,该字段取值不相等的记录也可以查询出来。外连接查询包括左连接查询和右连接查询。其基本语法如下:
SELECT 属性名列表
FROM 表名1 LEFT | RIGHT JOIN 表名2
ON 表名 1.属性名1 = 表名2.属性名2;
customers 表:
cust_id|cust_name|
-------+---------+
1|A |
2|B |
3|C |
orders 表:
order_id|cust_id|
--------+-------+
1| 1|
2| 1|
3| 3|
4| 3|
左连接:
SELECT customers.cust_id, customers.cust_name,orders.order_id
FROM customers LEFT OUTER JOIN orders
ON customers.cust_id = orders.cust_id;
结果:
cust_id|cust_name|order_id|
-------+---------+--------+
1|A | 1|
1|A | 2|
3|C | 3|
3|C | 4|
2|B | |
右连接:
SELECT customers.cust_id, customers.cust_name,orders.order_id
FROM customers RIGHT OUTER JOIN orders
ON customers.cust_id = orders.cust_id;
结果为:
cust_id|cust_name|order_id|
-------+---------+--------+
1|A | 1|
1|A | 2|
3|C | 3|
3|C | 4|
4 子查询
子查询是将一个查询语句嵌套在另一个查询语句中。内层查询语句的查询结果,可以为外层查询语句提供查询条件。因为在特定情况下,一个查询语句的条件需要另一个查询语句来获取。例如,现在需要从学生成绩表中查询计算机系学生的各科成绩。那么,首先就必须知道哪些课程是计算甲系学生选修的。因此,必须先查询计算机系学生选修的课程,然后根据这些课程来查询计算机系学生的各科成绩。通过子查询,可以实现多表之间的查询。子查询中可能包括in、not in、any、all、exists和not exists等关键字。子查询中还可能包含比较运算符,如“=”、“!=”、“>”和“<”等。本小节将详细讲解子查询的知识。
4.1 带in关键字的子查询
一个查询语句的条件可能落在另一个select语句的查询结果中,这可以通过in关键字来判断,例如,要查询哪些同学选择了计算甲系开设的课程。先必须从课程表中查询出计算机系开设了哪些课程。然后再从学生表中进行查询。如果学生选修的课程在前面查询出来的课程中,则查询出该同学的信息。这可以用带in关键字的子查询来实现。
下面查询employee表中的记录。这些记录的d_id字段的值必须在department表中出现过。select语句如下:
SELECT *
FROM employee
WHERE d_id IN
(
SELECT d_id FROM department
);
4.2 带比较运算符的子查询
子查询可以使用比较运算符。这些比较运算符包括=、!=、>、>=、<、<=和<>等。其中,<>与!=是等价的。比较运算符在子查询时使用的非常广泛。如查询分数、年龄、价格和收入等。
下面从computer_stu表中查询获得一等奖学金的学生的学号、姓名和分数。各个等级的奖学金的最低分存储在scholarship表中。下面来查询谁是一等奖学金的得主。首先必须从scholarship表中查询出一等奖学金要求的最低分。然后再从computer_stu表中查询哪些学生的分数高于这个最低分。select语句如下:
SELECT id, name, score FROM computer_stu
WHERE score>=
(
SELECT score FROM scholarship WHERE level =1
);
4.3 带exists关键字的子查询
exists关键字表示存在。使用exists关键字时,内层查询语句不返回查询的记录。而是返回一个真假值。如果内层查询语句查询到满足条件的记录,就返回一个真值(true),否则,将返回一个假值(false)。当返回的值为true时,外层查询语句将进行查询;当返回的为false时,外层查询语句不进行查询或者查询不出任何记录。
下面如果department表中存在d_id取值为1003的记录,则查询employeed表的记录。select语句如下:
SELECT * FROM employee
WHERE EXISTS
(
SELECT d_name FROM department WHERE d_id=1003
);
4.4 带any关键字的子查询
any关键字表示满足其中任一条件。使用any关键字时,只要满足内层查询语句返回的结果中的任何一个,就可以通过该条件来执行外层查询语句。例如,需要查询哪些同学能够获得奖学金。那么,首先必须从奖学金表中查询出各种奖学金要求的的最低分。只要一个同学的成绩高于不同奖学金最低分的任何一个,这个同学就可以获得奖学金。any关键字通常与比较运算符一起使用。例如,>any表示大于任何一个值,=any表示等于任何一个值。
下面来查询到底谁能得奖学金。先需要从scholarship表中查询出各种奖学金的最低分。然后,从computer_stu表中查询哪些人的分数高于其中任何一个奖学金的最低分。select语句代码如下:
SELECT * FROM computer_stu
WHERE score>= ANY
(
SELECT score FROM scholarship
);
4.5 带all关键字的子查询
all关键字表示满足所有条件。使用all关键字时,只有满足内层查询语句返回的所有结果,才可以执行外层查询语句。例如,需要查询哪些同学能够获得一等奖学金。首先必须从奖学金表中查询出各种奖学金要求的最低分。因为一等奖学金要求的分数最高。只有当同学的成绩高于所有的奖学金最低分时,这个同学才可能获得一等奖学金。all关键字也经常与比较运算符一起使用。例如,>all表示大于所有值,<all表示小于所有值。
下面从computer_stu表中查询出哪些同学可以获得一等奖学金。奖学金的信息存储在scholarship表中。先需要从scholarship表中查询出各种奖学金的最低分。然后,从computer_stu表中查询哪些人的分数高于所有奖学金的最低分。select语句代码如下:
SELECT * FROM computer_stu
WHERE score>= ALL
(
SELECT score FROM scholarship
);
4.6 合并查询结果
合并查询结果是将多个select语句的查询结果合并到一起。因为某种情况下,需要将几个select语句查询出来的结果合并起来显示。例如,现在需要查询公司甲和公司乙这两个公司所有员工信息。这就需要从公司甲中查询出所有员工的信息,再从公司乙中查询出所有员工的信息。然后将两次的查询结果合并到一起。进行合并操作使用union和union all 关键字。
使用union关键字时,数据库系统会将所有的查询结果合并到一起,然后去除掉相同的记录。而union all关键字则只是简单的合并到一起。其语法规则如下:
SELECT 语句 1
UNION | UNION ALL
SELECT 语句 2
UNION | UNION ALL...
SELECT 语句 n;
从上面可以知道,可以合并多个select语句的查询结果。而且,每个select语句之间使用union或union all关键字连接。
下面从department表和employee表中查询d_id字段的取值。然后通过union关键字将结果合并到一起。语句如下:
SELECT d_id FROM department
UNION
SELECT d_id FROM employee;
下面使用union all关键字将结果合并到一起。语句如下:
SELECT d_id FROM department
UNION ALL
SELECT d_id FROM employee;
5 为表和字段取别名
在查询时,可以为表和字段取一个别名。这个别名可以代替其指定的表和字段。
5.1 为表取别名
基本形式如下:
表名 表的别名
5.2 为字段取别名
基本形式如下:
属性名 [AS] 别名
6 使用正则表达式查询
6.1 查询以特定字符或字符串开头的记录
使用字符“^”可以匹配以特定字符或字符串开头的记录。
下面从info表name字段中查询以字母‘L’开头的记录。SQL代码如下:
SELECT * FROM info WHERE name REGEXP '^L';
6.2 查询以特定字符或字符串结尾的记录
使用字符“$”,可以匹配以特定字符或字符串结尾的记录。
下面从info表name字段中查询以字母c结尾的记录。SQL代码如下:
SELECT * FROM info WHERE name REGEXP 'c$';
6.3 用符号“.”来代替字符串中的任意一个字符
下面从info表name字段中查询以字母‘L’开头,以字母‘y’结尾,中间有两个任意字符的记录。SQL代码如下:
SELECT * FROM info WHERE name REGEXP '^L..y$';
6.4 匹配指定字符中的任意一个
使用方括号([])可以将需要查询字符组成一个字符集。只要记录中包含方括号中的任意字符,该记录将会被查询出来。例如,通过“[abc]”可以查询包含a、b和c等3个字母中的任何一个记录。
下面从info表name字段中查询包含c、e和o 3个字母中任意一个的记录。SQL代码如下:
SELECT * FROM info WHERE name REGEXP '[ceo]';
使用方括号([])可以指定集合的区间。如“[a-z]”表示从a-z的所有字母;“[0-9]”表示从0-9的所有数字;“[a-z0-9]”表示包含所有的小写字母和数字。
下面从info表name字段中查询包含数字或者字母a、b和c的记录。SQL代码如下:
SELECT * FROM info WHERE name REGEXP '[0-9a-c]';
6.5 匹配指定字符以外的字符
使用“[^字符集合]” 可以匹配指定字符以外的字符。
下面从info表name字段中查询包含’a’到‘w’字母和数字以外的字符的记录。SQL代码如下:
SELECT * FROM info WHERE name REGEXP '[^a-w0-9]';
6.6 匹配指定字符串
正则表达式可以匹配字符串。当表中的记录包含这个字符串时,就可以将该记录查询出来。如果指定多个字符串时,需要用符号“|”隔开。只要匹配这些字符串中的任意一个即可。
下面从info表name字段中查询包含’ic’的记录。SQL代码如下:
SELECT * FROM info WHERE name REGEXP 'ic';
下面从info表name字段中查询包含ic、uc和ab这3个字符串中任意一个记录。SQL代码如下:
SELECT * FROM info WHERE name REGEXP 'ic|uc|ab';
6.7 使用“”和“+”来匹配多个字符
*正则表达式中,“**”和“+”都可以匹配多个该符号之前的字符。但是,“+”至少表示一个字符,而 * 可以表示0个字符。
下面从info表name字段中查询字母‘c’之前出现过‘a’的记录。SQL代码如下:
SELECT * FROM info WHERE name REGEXP 'a*c';
6.8 使用或者来指定字符串连续出现的次数
下面从info表name字段中查询出现过’a’3次的记录。SQL代码如下:
SELECT * FROM info WHERE name REGEXP 'a{3}';
下面从info表name字段中查询出现过’a’2-3次的记录。SQL代码如下:
SELECT * FROM info WHERE name REGEXP 'a{2,3}';