学前必备知识
范围查询是用来查询给定的两个值之间的数据,通常使用 BETWEEN.…AND 和 NOT.…BETWEEN…AND 来指定范围条件。使用 BETWEEN…AND 查询条件时,指定的第一个值必须小于第二个值。因为 BETWEEN.…AND 实质是查询条件 大于或等于第一个值,并且小于或等于第二个值
的简写形式,即 BETWEEN…AND
要包括两端的值,等价于比较运算符 >=....<=
。
【例1】在 student 表中,显示年龄在 20~22 岁之间的学生信息。SQL 语句如下:
SELECT * FROM student WHERE 年龄 BETWEEN 20 AND 22;
查询结果如下图所示:
【例2】在 student 表中,显示年龄不在 20~22 岁之间的学生信息。SQL 语句如下:
SELECT * FROM student WHERE 年龄 NOT BETWEEN 20 AND 22;
查询结果如下图所示:
【例3】在 bookinfo_zerobasis 零基础系列图书信息表中,查询数据录入时间在 2017年12月1日 和 2018年12月1日 之间的图书信息。SQL 语句如下:
SELECT ISBN,BookName,INTime AS '录入时间'
FROM bookinfo_zerobasis
WHERE INTime BETWEEN '2017-12-1' AND '2018-12-1';
通过 GETDATE() 函数和 DATEADD() 函数,获取当天的日期和前一天的日期,再通过使用 BETWEEN---AND
来查询出在这两个日期之间的数据。例如,使用如下代码可获得当天的日期:
SELECT GETDATE();
查询结果如下图所示:
【例4】在 bookinfo_zerobasis 零基础系列图书信息表中,查询数据录入时间在 2017年10月26日 前一天的图书信息。SQL 语句如下:
SELECT ISBN,BookName,INTime AS '数据录入时间'
FROM bookinfo_zerobasis
WHERE INTime BETWEEN DATEADD(DAY,-1,'2017-10-26') AND '2017-10-26';
在不同的 DBMS 中,系统都提供了许多用于处理日期和时间的函数,通过这些函数可以实现计算特定日期和时间。
1、转换日期格式
有时数据库表中存储的日期可能会是不规范的日期形式,如 21.04.07
。为了方便用户的查看,需要将日期转换为四位数的年份,同时改变日期格式如 2021-04-07
(“年-月-日”格式)。为了解决这一问题,从以下两点来进行介绍。
(1) 把长日期格式数据转换为短日期格式数据
函数表达式 SELECT CONVERT(CHAR(10),GETDATE(),120); 可以将日期转换成 yyyy-mm-dd 格式时间。其中,120 是格式代码,CHAR(10) 是指取出前 10 位字符。SQL Server 数据库并不支持分开的 TIME、DATE 和 TIMESTAMP 数据类型,而是支持单一的 DATETIME 数据类型,用于定义保存符合的日期和时间值。在 SOL Server 中,可使用 CONVERT 函数实现类型的转换。语法格式如下:
CONVERT(date_type[(length)],expression,style)
参数说明:
(2) 将日期格式中的 -
转换为 /
。REPLACE() 函数可以实现寻找列值中的 -
,将其替换成 /
的功能。
【例5】将如 2021-04-07 11:49:23.030
的日期格式转换成如 2021/04/07
的日期格式。SQL 语句如下:
SELECT REPLACE(CONVERT(CHAR(10), GETDATE(), 120), '-', '/');
要想计算两个日期的间隔天数,可以使用 DATEDIFF() 函数实现。DATEDIFF() 函数的语法格式如下:
DATEDIFF(datepart, startdate, enddate)
参数说明:
【例6】例如,利用 DATEDIFF() 函数查询 2021年4月7日 到 2021年3月29日 之间的天数。SQL 语句如下:
SELECT DATEDIFF(DAY, '2021-3-29', '2021-4-7') AS '科目二考试通过天数';
查询结果如下图所示:
注意: enddate 减 startdate,如果 startdate 比 enddate 晚,则返回负值;当结果超出整数值范围,DATEDIFF 将产生错误。
3、按指定日期查询数据
(1) DAY() 函数。DAY() 函数返回代表指定日期的天的日期部分的整数。其语法格式:
DAY(date)
参数说明:
下面举例介绍一下 DAY() 函数的用法,返回月份值,SQL 语句如下:
SELECT DAY(0) AS MY_DAY1, DAY('04/07/2021') AS MY_DAY2;
-- 注意:SQL Server将date为0解释为01/01/1900。
查询结果如下图所示:
(2) MONTH() 函数。要实现按月查询数据可以使用日期函数 MONTH()。该函数的语法格式如下:
MONTH(date)
参数说明:
MONTH() 函数能够将日期时间表达式 date 中的月份返回,返回的月份以数值1~12 来表示,1 代表一月、2 代表二月,以此类推。同样需要注意的是如果将 date 设置为 0,SQL Server 会将 0 视为 1900年1月1日。下面举例介绍一下 MONTH() 函数的用法。如下面的示例从日期 04.07.2021 中返回月份数,返回结果为 4。
SELECT MONTH('04.07.2021'); -- 4
(3) YEAR() 函数。YEAR() 函数用于返回表示指定日期中的年份的整数。其语法格式如下:
YEAR(date)
参数说明:
注意:
下面举例介绍一下 YEAR() 函数的用法,如下面示例返回指定日期的年份信息:
SELECT
YEAR(-1) AS MY_YEAR1,
YEAR(-2) AS MY_YEAR2,
YEAR(0) AS MY_YEAR3,
YEAR(9) AS MY_YEAR4,
YEAR('04/07/2021') AS MY_YEAR5,
DATEPART(yy, '04/07/2021') AS MY_YEAR6;
查询结果如下图所示:
【例7】按指定日期的月和年查询 bookinfo 图书信息表中图书的出版日期在 2016年 的图书信息。SQL 语句如下:
SELECT BookName,Type,pDate FROM bookinfo
WHERE YEAR(pDate)=2015;
查询结果如下图所示:
小结:通过本节的学习,不仅需要掌握使用 BETWEEN…AND
语句进行范围查询,可以查询数字、日期之间的范围,还可以通过使用 NOT…BETWEEN…AND
语句来实现不在两个数之间的数据查询。除了范围查询之外,还介绍了日期时间的查询语句及用到的时间日期函数。
如果想把几个单一条件组合成一个复合条件,这就需要使用逻辑运算符 NOT、AND 和 OR 才能完成复合条件查询。本小节将介绍在 SELECT 语句中使用逻辑运算符进行查询的方法。
在查询表时,如果想要满足两个给定的条件,可以在 WHERE 子句中使用 AND 运算符来实现。AND 运算符表示 与(并且)
的关系,在进行查询时,既要满足给定的第一个条件,也要同时满足给定的第二个条件,如果不满足两个查询条件的其中一个,这样的记录就会被排除掉。AND 运算符的真值表如下:
【例8】在 goods 商品信息表中,查询商品的本店价格(shop_price) 大于 3000 元并且小于 6000 元的所有商品的 id(goods_id)、名称(goods_name)和本店价格(shop_price)。SQL 语句如下:
SELECT goods_id,goods_name,shop_price
FROM goods
WHERE shop_price > 3000 AND shop_price < 6000;
查询结果如下图所示:
说明:在定义查询语句时,在WHERE子句中可以设置多个筛选条件,可以同时使用多个AND运算符来连接多个条件表达式,只有同时满足所有查询条件的记录才会被查询出来。
【例9】按指定日期的月和年查询 bookinfo 图书信息表中 零基础系列
图书的出版日期在 2017年10月份 的图书信息。SQL 语句如下:
SELECT BookName,Type,pDate FROM bookinfo
WHERE YEAR(pDate)=2017 AND MONTH(pDate)=10 AND Type='零基础系列';
在查询表时,如果想要满足两个给定条件的其中一个时,可以在 WHERE 子句中使用 OR 运算符来实现。OR 运算符表示 或
的关系,即满足第一个给定的条件或满足第二个给定的条件,如果不满足两个查询条件中的任何一个,这样的记录就会被排除掉。OR 运算符的真值表如下表所示:
【例10】用 OR 进行查询。查询学号是 B001
或者是 B003
的学生信息。SQL 语句如下:
USE student;
SELECT * FROM student WHERE 学号='B001' OR 学号='B003';
查询结果如下图所示:
同样,在WHERE语句中可以同时使用多个OR运算符来连接多个条件表达式,只要满足任何一个查询条件的记录就会被查询出来。
【例11】用 OR 进行查询。查询学号是 B001
或者是 B003
或者是年龄为 20 岁的学生信息。SQL 语句如下:
SELECT * FROM student WHERE 学号='B001' OR 学号='B003' OR 年龄=20;
在查询表时,如果需要查询不满足给定条件的数据,可以在 WHERE 子句中使用 NOT 运算符来实现。NOT 运算符表示 非
的关系,即不满足所给定的条件。
【例12】查询年龄不为 20 岁的学生信息。SQL 语句如下:
SELECT * FROM student WHERE NOT 年龄=20;
查询结果如下图所示:
在查询中也可以将 AND 运算符、OR 运算符和 NOT 运算符综合起来使用,但这 3 个运算符拥有不同的优先顺序,它们的优先级别按照由高到低的排列顺序如下图所示:
即 NOT 优先级最高,AND 次之,OR 的优先级最低。对运算符优先级别的了解,在使用时非常重要。如果不掌握运算符的优先级别,在使用时就达不到预期的效果。
【例13】在 goods 商品信息表中,应用 OR 运算符和 AND 运算符组合查询商品信息,查询出商品分类id(cat_id)为 191,或商品分类 id 为 123,并且商品的本店价格(shop_price)大于 2000 元的所有商品。SQL 语句如下:
USE shop;
SELECT cat_id,goods_name,shop_price
FROM goods
WHERE cat_id=191 OR cat_id=123 AND shop_price>2000;
查询结果如下图所示:
由上图中的运行结果可以看出,商品分类 id 为 191 并且商品本店价格小于 2000元 的商品也被查询出来,显然没有达到预期的效果。出现该问题的原因在于求值的顺序,SQL 在处理 OR 运算之前,会优先处理 AND 运算,所以在结果中查询出商品分类 id 为 123 且商品本店价格大于 2000元 的商品,以及商品分类 id 为 191 的所有商品。要解决这个问题,可以使用小括号对运算符和查询条件进行分组。SQL 语句如下:
USE shop;
SELECT cat_id,goods_name,shop_price
FROM goods
WHERE (cat_id=191 OR cat_id=123) AND shop_price>2000;
查询结果如下图所示:
说明:因为小括号具有比 AND、OR 或 NOT 运算符更高的优先级,所以在 WHERE 子句中使用不同的逻辑运算符时,都应该使用小括号对运算符和查询条件进行明确分组。
【练习1】在 goods 商品信息表中,使用 NOT 运算符和 AND 运算符查询商品信息,查询出商品分类id(cat_id)不是 191 和 123 的所有商品分类 id、商品名称(goods_name)和商品本店价格(shop_price)。
【练习2】在 student 表中,要查询年龄大于21岁女生或者年龄大于等于19岁的男生信息。
【练习3】在 student 表中,查询年龄大于20岁的女生或者年龄大于22岁的男生,并且电话号码都是 23451
的学生信息。
总结:本小节主要讲解了将多个条件表达式通过使用逻辑运算符结合在 WHERE 子句中来完成查询功能。通过本小节的学习,读者可以掌握 AND、OR 和 NOT 运算符的使用,并了解这些运算符的优先级。
在对表中的数据进行查询时,有时需要查询出多个条件中满足一个条件的数据,这种情况可以使用 OR 运算符,但是对于较多的条件来说使用 OR 运算符并不方便,例如,在表中查询出省份为 吉林省、辽宁省、黑龙江省
的数据,使用 OR 运算符就会比较烦琐。此时可以使用 IN 操作符代替 OR 运算符来完成查询任务。
使用 IN 操作符可以判断某个字段的值是否在指定的集合中。如果字段的值在集合中,则满足查询条件,该记录将被查询出来;如果不在集合中,则不满足查询条件。使用 IN 操作符查询数据的基本语法格式如下:
SELECT column_name
FROM table_name
WHERE column_name IN (value1, value2,. . .)
参数说明:
【例14】在 goods 商品信息表中,查询出商品分类 id(cat_id)为 191、123 和 131 的商品分类 id、商品名称(goods_name)和商品本店价格(shop_price)。SQL 语句如下:
SELECT cat_id,goods_name,shop_price
FROM goods
WHERE cat_id IN(191,123,131);
查询结果如下图所示:
【练习4】在 course 表中,查询 课程编号
是 k01,k03,k04 的课程信息。
在 IN 操作符后的值列表中还可以使用算术表达式。【例15】在 goods 商品信息表中,查询出商品本店价格(shop_price) 为 3799-100
、3799 和 3799+100
三种价格的商品名称(goods_name)和商品本店价格。SQL 语句如下:
USE shop;
SELECT goods_name,shop_price FROM goods
WHERE shop_price IN(3799-100,3799,3799+100);
查询结果如下图所示:
在使用 IN 操作符对数据进行查询时,不但可以使用数值类型和字符类型的数据作为值列表,还可以使用列名作为值列表。下面使用数值作为 IN 操作符的查询条件将两个列名作为值列表来实现查询。
【例16】在 goods 商品信息表中,查询出商品的市场价格(market price)或本店价格(shop_price)为 3799 的商品名称(goods_name)、商品市场价格和本店价格。SQL 语句如下:
SELECT goods_name,market_price,shop_price FROM goods
WHERE 3799 IN(market_price, shop_price);
NOT IN 操作符可以查询出给定条件以外的数据。利用 NOT IN 操作符查询条件的基本语法格式如下:
SELECT column_name
FROM table_name
WHERE column_name NOT IN (value1, value2,. . .)
参数说明:
【例17】在 course 表中,课程代号不是 k01、k03 和 k04 的课程信息。SQL 语句如下:
USE student;
SELECT * FROM course
WHERE 课程代号 NOT IN('k01','k03','k04');
查询结果如下图所示:
使用NOT IN 查询后两行的数据,前提条件是需要知道表中共有多少行数据。例如,数据表中有 5 行数据,在查询中先通过使用 TOP 关键字将前 3 行数据查询出来,再使用 NOT IN 操作符将后两行数据查询出来。
【例18】在 course 表中,有5条记录,查询最后两行的数据。SQL 语句如下:
SELECT * FROM course
WHERE 课程代号 NOT IN(SELECT TOP 3 课程代号 FROM course);
查询结果如下图所示:
总结:本小节主要讲解了在 WHERE 子句中通过 IN 操作符和 NOT IN 操作符来实现查询功能。通过本小节的学习,读者可以掌握 IN 操作符和 NOT IN 操作符的使用。
在对表中数据进行查询时,常常会用到模糊查询。模糊查询可以轻松地查询出比较模糊的数据。例如,查询姓名列中姓 诸葛
的数据、查询用户邮箱列中含有 qq
的数据等。
前面介绍的所有操作符都是针对已知的值进行过滤的。无论是匹配一个值还是多个值,或者查询某个范围的值,在过滤数据时提供的这些值都是已知的。而有时在查询表中数据时需要返回符合某种匹配格式的所有记录,这时就需要使用 LIKE 或 NOT LIKE 谓词来指定模糊查询条件。定义模糊查询条件需要使用通配符在字符串内查找指定的搜索模式,所以读者需要了解通配符及其含义。通配符即用来匹配值的一部分的特殊字符。常用的通配符及其含义如下表所示:
LIKE 谓词通过使用通配符可以指定任何的模糊查询条件,下面将介绍几个使用 LIKE 谓词来实现模糊查询的例子:
-- 1.查询出某列中包含 amo 字符的数据,其中amo可以出现在任意位置。
WHERE 列名 LIKE '%amo%'
-- 2.查询出某列中包含amo字符的数据,其中amo出现在开头位置。
WHERE 列名 LIKE 'amo%'
-- 3.查询出某列中包含amo字符的数据,其中amo出现在结尾位置。
WHERE 列名 LIKE'%amo'
-- 4.查询出某列中前两个字符为am、后一个字符为任意字符的数据。
WHERE 列名 LIKE 'am_'
-- 5.查询出某列中前一个字符为任意字符、后两个字符为mo的数据。
WHERE 列名 LIKE '_mo'
-- 6.查询出某列中以a字符或b字符开头的数据
WHERE 列名 LIKE '[ab]%'
-- 7.查询出某列中以a~e之间的字符开头的数据,其中包括a和e
WHERE 列名 LIKE '[a-e]%'
-- 8.查询出某列中不是以a字符或b字符开头的数据
WHERE 列名 LIKE '[^ab]%'
-- 9.查询出某列中不是以 a~e 之间的字符开头的数据
WHERE 列名 LIKE '[^a-e]%'
【练习5】在 student 表中,查询姓 李
并且联系方式是以 2
打头的学生信息。
【练习6】在 student 表中,查询姓 刘
并且名字只有两个字的学生信息。
【练习7】在 student 表中,查询姓 李
并且末尾字是 丽
的学生信息。
【练习8】在 student 表中,查询联系方式以 3451
结尾并且开头数字位于 1~5
之间的学生信息。
【练习9】在 grade 表中,查询学号是 B001
~B003
之间的学生成绩信息。
【练习10】在 student 表中,查询联系方式以 3451
结尾,但不以 2
开头的学生信息。
NOT LIKE 的含义与 LIKE 关键字正好相反,查询结果将返回不符合匹配模式查询。
在使用通配符查询数据时,数据中可能也包含着通配符。例如,表中的某个列可能存储着包含百分号 %
的折扣值,此时如果使用 %
通配符进行数据查询,可能会查不到想要查询的数据,这时可以使用 ESCAPE 关键字定义转义字符来解决这个问题。当把定义的转义字符放在通配符之前时,该通配符就被解释为普通字符。例如,查询出某列中以字符串 10%
结尾的数据,代码如下:
WHERE 列名 LIKE '%10#%' ESCAPE '#';
上述代码中,第一个 %
为通配符,#
为定义的转义字符,其后面的 %
即被解释为普通字符。
【例19】在 users 用户信息表中,查询用户注册邮箱(email) 名称中含有字符 _
的用户 id(user_id)、注册邮箱和用户出生日期(birthday)。SQL 语句如下:
USE shop;
SELECT user_id,email,CONVERT(VARCHAR(10),birthday,120) AS birthday
FROM users
WHERE email LIKE '%/_%' ESCAPE '/';
查询结果如下图所示:
总结:本小节主要讲解了什么是通配符,以及如何在 WHERE 子句中使用通配符。通过本小节的学习,读者可以掌握应用 LIKE 谓词和通配符进行模糊查询。