MySQL选择查询,其间为第二个字符,数字范围为0到9

时间:2016-03-06 13:56:44

标签: mysql

我想从第一个字符为*的表中选择数据,第二个字符的数字从0到9

我使用的代码正在运行并提供*0123456* *34567*等字符串:

SELECT * FROM `MyTable` WHERE SUBSTRING(MyColumn,1,1) = "*" AND    
(SUBSTRING(MyColumn,2,1) ="0" OR SUBSTRING(MyColumn,2,1) BETWEEN 1 AND 10) ;

但是当我更改查询以缩短它时,它会给出字符串,这些字母表我不想要

SELECT * FROM `MyTable` WHERE SUBSTRING(MyColumn,1,1) = "*" AND 
(SUBSTRING(MyColumn,2,1) BETWEEN 0 AND 10) ;

为什么0在这个查询中没有按预期工作?

2 个答案:

答案 0 :(得分:3)

您正在看到此问题,因为MySQL会在将其与0和10进行比较之前尝试将非数字字符转换为整数。由于MySQL的转换规则,非数字字符串始终被视为等于零,条件BETWEEN 0 AND 10为真。

-- The second character 'B' is equal to 0 after casting
> SELECT SUBSTRING('*BC', 2, 1) = 0;
+----------------------------+
| SUBSTRING('ABC', 2, 1) = 0 |
+----------------------------+
|                          1 |
+----------------------------+

由于您要匹配特定模式,我建议您使用REGEXP匹配进行匹配,而不是将其整理到子字符串中。

SELECT * 
FROM `MyTable` 
WHERE MyColumn REGEXP '(^\\*[0-9])'

示例:

> SELECT '*123' REGEXP '^\\*[0-9]';
+---------------------------+
| '*123' REGEXP '^\\*[0-9]' |
+---------------------------+
|                         1 |
+---------------------------+

 > SELECT '*A23' REGEXP '^\\*[0-9]';
+---------------------------+
| '*A23' REGEXP '^\\*[0-9]' |
+---------------------------+
|                         0 |
+---------------------------+

此处的模式匹配分解为:

  • ^字符串的开头
  • \\*匹配文字'*',需要转义反斜杠
  • [0-9]后跟一位数字。

如果您在BETWEEN中使用带引号的字符串,可以使用您的方法并避免广播:(SUBSTRING(msgbody,2,1) BETWEEN '0' AND '9')

> SELECT SUBSTRING('*BC', 2, 1) BETWEEN '0' AND '9';
+--------------------------------------------+
| SUBSTRING('*BC', 2, 1) BETWEEN '0' AND '9' |
+--------------------------------------------+
|                                          0 |
+--------------------------------------------+

 > SELECT SUBSTRING('*99', 2, 1) BETWEEN '0' AND '9';
+--------------------------------------------+
| SUBSTRING('*99', 2, 1) BETWEEN '0' AND '9' |
+--------------------------------------------+
|                                          1 |
+--------------------------------------------+

但我更喜欢REGEXP方法,因为它表示您希望匹配的整个模式作为一个条件。我发现它更容易阅读,因为字符位置是内置在表达式中的,而不是需要从substring()解码它们。在其中任何一个选项中,我都希望MySQL不会使用索引。

答案 1 :(得分:0)

你过度复杂化了。在这种特定情况下,如果你说

  

希望从具有第一个字符*的表中选择数据,并且第二个字符具有从0到9的数字

然后你想要的所有东西都来自' * 0 ......'到' * 9 ....'。

所以你想要,

WHERE MyColumn >= '*0' AND SUBSTR(MyColumn, 1, 2) <= '*9';

如果您知道MyColumn的值不会超过,例如&#34; * 9ZZZZZZZZ&#34;那么查询会更有效率。然后你会问

WHERE MyColumn >= '*0' AND MyColumn <= '*9ZZZZZZZZ'

或者因为通常按照字典顺序排列的是&#39;:#,然后你不想要它,

WHERE MyColumn >= '*0' AND MyColumn <= '*:'

允许更好地使用MyColumn上的索引。