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}';
消息盒子

# 暂无消息 #

只显示最新10条未读和已读信息