本节要点

LIKE通配符
组合WHERE子句

LIKE通配符

上节课我们讲解了一些比较简单的操作符,还剩下EXISTS和LIKE没有讲解。

关于EXISTS,主要是和子查询语句一起配合使用的,所以我会放在后面讲子查询的那节课里去讲。这节课主要来讲解下LIKE操作符。

LIKE,从这个单词的英文含义就可以大概猜到,它是用来实现查询字段的值与某个值相似的功能。

比如,我们想查出所有姓陈的同学,那么就可以按学生姓名的第一个字为“陈”去查询。

或者说,如果老师表中保存了所有老师的身份证号,那如何取出70年代出生的所有老师?

这就需要使用LIKE操作符。LIKE操作符一般用来与通配符一起配合使用。

常见的通配符有百分号%、下划线_、方括号[]。基本上所有的数据库都支持百分号%、下划线_通配符,支持方括号[]通配符的数据库比较少。

百分号通配符%,用来匹配0~多个任意字符。也就是说,基本上所有字符,无论长度多少,都能匹配。
下划线通配符_,用来匹配1个任意字符。注意,必须是1个字符。
方括号通配符[],是用来匹配1个方括号中列出的字符集合中的一个字符。因为用的比较少,就不讲了。

下面通过几个例子,来讲解如何使用通配符进行查询。

(1)、如何查询所有姓陈的学生?姓陈的学生的特点就是,姓名的第一个字符是“陈”,而后面的字符不确定。所以可以使用如下语句来查询:

SELECT * FROM STUDENT WHERE student_name LIKE '陈%';

(2)、如何查询学生姓名的最后一位是“慧”字的学生?

SELECT * FROM STUDENT WHERE student_name like '%慧';

(3)、如何查询姓陈且姓名只有两个字的同学?

SELECT * FROM student WHERE student_name LIKE '陈_’;

注意跟第一个例子进行对比下。

(4)、如何查询所有叫陈某军的同学?

这里有两种写法,第一种:

SELECT * FROM student WHERE student_name LIKE '陈_军';

这种写法,只能匹配出姓名为3个字的同学。比如“陈军”同学,就不能匹配出来。

第二种写法:

SELECT * FROM student WHERE student_name LIKE '陈%军';

这种写法,可以同时匹配出姓名为2个字和3个字的同学。这里,就可以匹配出“陈军”同学,因为百分号通配符,是可以匹配0个任意字符的。

(5)、如何匹配姓名中,任意位置出现“慧”字的同学?

SELECT * FROM STUDENT WHERE student_name like '%慧%';

使用上面这种写法,在“慧”字的前后,都加上百分号通配符%就可以了。

所以说,通配符使用起来是不是很灵活呢。但是,在使用通配符的过程中,还是需要有一些要注意的地方。

使用通配符的注意点:
不要过度使用通配符;
如果确实需要使用,也尽量不要把通配符用在匹配模式的开始处;
要特别注意通配符的位置,否则很有可能返回的结果与预期不一致;

那么,请大家再思考一下开头提到的一个问题:如果老师表中保存了所有老师的身份证号,那如何取出70年代出生的所有老师?

组合WHERE子句

先来看下面两个问题:

如何取出所有姓陈的男同学?

如何取出所有姓陈的同学或男同学?

在前面的例子中,我们都是从表中按单一条件查询。那如果像上面这样的查询需求,该怎么去写呢?

比如:如何取出所有姓陈的男同学?这个查询需求里就包含了两个条件,一个是姓名是姓“陈”,另一个是性别为“男”。

其实,SQL语言里,也提供了一类操作符,允许我们将多个查询条件组合起来。

这一类操作符,就叫做逻辑操作符,它包括AND操作符和OR操作符两个。

AND操作符两边的条件,都必须同时满足才会返回;而OR操作符两边的条件,只要满足任一一个,就会返回。

(1)、如何取出所有姓陈的男同学?

SELECT * FROM student
WHERE student_name LIKE '陈%' AND gender = '男';

(2)、如何取出所有姓陈的同学或男同学?

SELECT * FROM student
WHERE student_name LIKE '陈%' OR gender = '男';

仔细对比一下上面两个例子,这就是AND操作符和OR操作符的区别。

可如果我们的查询需求中,包含的条件更多,不止两个的时候,怎么办呢?比如下面这个:

(3)、如何取出所有年龄大于15岁并且姓陈或男性同学?

这个题目其实是有歧义的,也就是说姓陈这个条件,是跟前面年龄大于15岁一起计算呢,还是跟后面的男性同学一起计算。

针对这个查询需求,其实是可以写出两个答案:

第一种:

SELECT * FROM student
WHERE age > 15 AND student_name LIKE '陈%' OR gender = '男';

第二种:

SELECT * FROM student
WHERE age > 15 AND (student_name LIKE '陈%' OR gender = '男');

这两种写法,查询出来的结果是不一样的。第二种写法,为了将姓陈的条件与男同学的条件放在一起计算,使用了小括号。如果不使用小括号,像第一种写法,姓陈的条件就与前面年龄大于15的条件,一起计算了。

所以,在有多个条件,且既有AND操作符,又有OR操作符时,一定要记得使用小括号,将需要放在一起计算的条件,括起来,以便消除歧义,否则可能会出现意想不到的结果。

我们来看一下下面这个例子:

第一种写法:

SELECT * FROM t_orders
WHERE
pay_status='1' AND ship_status='0'
OR
pay_status='0' AND payment='-1' OR ship_status='0';

第二种写法:

SELECT * FROM t_orders
WHERE
(
    pay_status='1' AND ship_status='0'
)
OR
(
    pay_status='0' AND ( payment='-1' OR ship_status='0' )
);

对于不使用括号的第一种写法,相信没有人能说得清楚WHERE条件到底想要表达的含义。而对于使用括号的第二种写法,虽然条件比较复杂,但相对来说,看起来清晰多了。

所以,以后在使用组合WHERE子句时,尽量都使用括号消除歧义。

picture loss