### 12.8.1 字符串比较函数和运算符 [](<>)[](<>)[](<>)[](<>) [](<>) **表 12.13 字符串比较函数和运算符** | 姓名 | 描述 | | --- | --- | | [`喜欢`](string-comparison-functions.html#operator_like) | 简单的模式匹配 | | [`不喜欢`](string-comparison-functions.html#operator_not-like) | 简单模式匹配的否定 | | [`STRCMP()`](string-comparison-functions.html#function_strcmp) | 比较两个字符串 | 如果给字符串函数一个二进制字符串作为参数,则生成的字符串也是一个二进制字符串。转换为字符串的数字被视为二进制字符串。这仅影响比较。 [](<>)[](<>) 通常,如果字符串比较中的任何表达式区分大小写,则以区分大小写的方式执行比较。 如果从内部调用字符串函数[**mysql**](mysql.html)客户端,二进制字符串使用十六进制表示法显示,具体取决于[`--binary-as-hex`](mysql-command-options.html#option_mysql_binary-as-hex).有关该选项的更多信息,请参阅[第 4.5.1 节,“mysql - MySQL 命令行客户端”](mysql.html). - [](<>) [`*`表达式`* 喜欢 *`拍`* [逃脱 '*`escape_char`*']`](string-comparison-functions.html#operator_like) [](<>) 使用 SQL 模式进行模式匹配。退货`1`(`真的`) 要么`0`(`错误的`)。如果要么*`表达式`*要么*`拍`*是`空值`,结果是`空值`. 模式不必是文字字符串。例如,它可以指定为字符串表达式或表格列。在后一种情况下,列必须定义为 MySQL 字符串类型之一(请参阅[第 11.3 节,“字符串数据类型”](string-types.html))。 根据 SQL 标准,[`喜欢`](string-comparison-functions.html#operator_like)基于每个字符执行匹配,因此它可以产生不同于[`=`](comparison-operators.html#operator_equal)比较运算符: ``` mysql> SELECT 'ä' LIKE 'ae' COLLATE latin1_german2_ci; +-----------------------------------------+ | 'ä' LIKE 'ae' COLLATE latin1_german2_ci | +-----------------------------------------+ | 0 | +-----------------------------------------+ mysql> SELECT 'ä' = 'ae' COLLATE latin1_german2_ci; +--------------------------------------+ | 'ä' = 'ae' COLLATE latin1_german2_ci | +--------------------------------------+ | 1 | +--------------------------------------+ ``` [](<>) 特别是,尾随空格总是很重要。这不同于与[`=`](comparison-operators.html#operator_equal)运算符,对于非二进制字符串中尾随空格的重要性 (`字符`,`VARCHAR`, 和`文本`values) 取决于用于比较的排序规则的 pad 属性。有关详细信息,请参阅[比较中的尾随空间处理](charset-binary-collations.html#charset-binary-collations-trailing-space-comparisons). 和[`喜欢`](string-comparison-functions.html#operator_like)您可以在模式中使用以下两个通配符: - `%`匹配任意数量的字符,甚至是零个字符。 - `_`只匹配一个字符。 ``` mysql> SELECT 'David!' LIKE 'David_'; -> 1 mysql> SELECT 'David!' LIKE '%D%v%'; -> 1 ``` 要测试通配符的文字实例,请在其前面加上转义字符。如果您不指定`逃脱`特点,`\`假定,除非[`NO_BACKSLASH_ESCAPE`](sql-mode.html#sqlmode_no_backslash_escapes)SQL 模式已启用。在这种情况下,不使用转义字符。 - `\%`匹配一个`%`特点。 - `\_`匹配一个`_`特点。 ``` mysql> SELECT 'David!' LIKE 'David\_'; -> 0 mysql> SELECT 'David_' LIKE 'David\_'; -> 1 ``` 要指定不同的转义字符,请使用`逃脱`条款: ``` mysql> SELECT 'David_' LIKE 'David|_' ESCAPE '|'; -> 1 ``` 转义序列应为一个字符长以指定转义字符,或为空以指定不使用转义字符。表达式必须在执行时计算为常量。如果[`NO_BACKSLASH_ESCAPE`](sql-mode.html#sqlmode_no_backslash_escapes)开启SQL模式,序列不能为空。 以下两个语句说明字符串比较不区分大小写,除非其中一个操作数区分大小写(使用区分大小写的排序规则或二进制字符串): ``` mysql> SELECT 'abc' LIKE 'ABC'; -> 1 mysql> SELECT 'abc' LIKE _utf8mb4 'ABC' COLLATE utf8mb4_0900_as_cs; -> 0 mysql> SELECT 'abc' LIKE _utf8mb4 'ABC' COLLATE utf8mb4_bin; -> 0 mysql> SELECT 'abc' LIKE BINARY 'ABC'; -> 0 ``` 作为标准 SQL 的扩展,MySQL 允许[`喜欢`](string-comparison-functions.html#operator_like)关于数值表达式。 ``` mysql> SELECT 10 LIKE '1%'; -> 1 ``` 笔记 MySQL 在字符串中使用 C 转义语法(例如,`\n`表示换行符)。如果你想要一个[`喜欢`](string-comparison-functions.html#operator_like)包含文字的字符串`\`,你必须加倍。(除非[`NO_BACKSLASH_ESCAPE`](sql-mode.html#sqlmode_no_backslash_escapes)启用 SQL 模式,在这种情况下不使用转义字符。)例如,搜索`\n`, 指定为`\\n`.搜索`\`, 指定为`\\\\`;这是因为反斜杠被解析器剥离一次,并且在进行模式匹配时再次剥离,留下一个反斜杠进行匹配。 例外:在模式字符串的末尾,可以将反斜杠指定为`\\`.在字符串的末尾,反斜杠代表它本身,因为没有任何内容可以转义。假设一个表包含以下值: ``` mysql> SELECT filename FROM t1; +--------------+ | filename | +--------------+ | C: | | C:\ | | C:\Programs | | C:\Programs\ | +--------------+ ``` 要测试以反斜杠结尾的值,您可以使用以下任一模式匹配这些值: ``` mysql> SELECT filename, filename LIKE '%\\' FROM t1; +--------------+---------------------+ | filename | filename LIKE '%\\' | +--------------+---------------------+ | C: | 0 | | C:\ | 1 | | C:\Programs | 0 | | C:\Programs\ | 1 | +--------------+---------------------+ mysql> SELECT filename, filename LIKE '%\\\\' FROM t1; +--------------+-----------------------+ | filename | filename LIKE '%\\\\' | +--------------+-----------------------+ | C: | 0 | | C:\ | 1 | | C:\Programs | 0 | | C:\Programs\ | 1 | +--------------+-----------------------+ ``` - [](<>) [`*`表达式`* 不喜欢 *`拍`* [逃脱 '*`escape_char`*']`](string-comparison-functions.html#operator_not-like) [](<>) 这与`不是 (*`表达式`* 喜欢 *`拍`* [逃脱 '*`escape_char`*'])`. 笔记 聚合查询涉及[`不喜欢`](string-comparison-functions.html#operator_not-like)与包含的列进行比较`空值`可能会产生意想不到的结果。例如,考虑下表和数据: ``` CREATE TABLE foo (bar VARCHAR(10)); INSERT INTO foo VALUES (NULL), (NULL); ``` 查询`SELECT COUNT(*) FROM WHERE bar LIKE '%baz%';`返回`0`.你可能会认为`SELECT COUNT(*) FROM WHERE bar NOT LIKE '%baz%';`会回来`2`.但是,情况并非如此:第二个查询返回`0`.这是因为`NULL 不喜欢 *`表达式`*`总是返回`空值`, 不管值*`表达式`*.对于涉及的聚合查询也是如此`空值`和比较使用[`不喜欢`](regexp.html#operator_not-regexp)要么[`不是正则表达式`](regexp.html#operator_not-regexp).在这种情况下,您必须明确测试`非空`使用[`要么`](logical-operators.html#operator_or)(并不是[`和`](logical-operators.html#operator_and)),如下所示: ``` SELECT COUNT(*) FROM foo WHERE bar NOT LIKE '%baz%' OR bar IS NULL; ``` - [](<>) [`STRCMP(*`expr1`*,*`expr2`*)`](string-comparison-functions.html#function_strcmp) [](<>) [`STRCMP()`](string-comparison-functions.html#function_strcmp)返回`0`如果字符串相同,`-1`如果根据当前排序顺序,第一个参数小于第二个参数,并且`1`否则。 ``` mysql> SELECT STRCMP('text', 'text2'); -> -1 mysql> SELECT STRCMP('text2', 'text'); -> 1 mysql> SELECT STRCMP('text', 'text'); -> 0 ``` [`STRCMP()`](string-comparison-functions.html#function_strcmp)使用参数的排序规则执行比较。 ``` mysql> SET @s1 = _utf8mb4 'x' COLLATE utf8mb4_0900_ai_ci; mysql> SET @s2 = _utf8mb4 'X' COLLATE utf8mb4_0900_ai_ci; mysql> SET @s3 = _utf8mb4 'x' COLLATE utf8mb4_0900_as_cs; mysql> SET @s4 = _utf8mb4 'X' COLLATE utf8mb4_0900_as_cs; mysql> SELECT STRCMP(@s1, @s2), STRCMP(@s3, @s4); +------------------+------------------+ | STRCMP(@s1, @s2) | STRCMP(@s3, @s4) | +------------------+------------------+ | 0 | -1 | +------------------+------------------+ ``` 如果排序规则不兼容,则必须将其中一个参数转换为与另一个兼容。看[第 10.8.4 节,“表达式中的排序规则强制性”](charset-collation-coercibility.html). ``` mysql> SET @s1 = _utf8mb4 'x' COLLATE utf8mb4_0900_ai_ci; mysql> SET @s2 = _utf8mb4 'X' COLLATE utf8mb4_0900_ai_ci; mysql> SET @s3 = _utf8mb4 'x' COLLATE utf8mb4_0900_as_cs; mysql> SET @s4 = _utf8mb4 'X' COLLATE utf8mb4_0900_as_cs; --> mysql> SELECT STRCMP(@s1, @s3); ERROR 1267 (HY000): Illegal mix of collations (utf8mb4_0900_ai_ci,IMPLICIT) and (utf8mb4_0900_as_cs,IMPLICIT) for operation 'strcmp' mysql> SELECT STRCMP(@s1, @s3 COLLATE utf8mb4_0900_ai_ci); +---------------------------------------------+ | STRCMP(@s1, @s3 COLLATE utf8mb4_0900_ai_ci) | +---------------------------------------------+ | 0 | +---------------------------------------------+ ```