我想从第一个字符为*
的表中选择数据,第二个字符的数字从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在这个查询中没有按预期工作?
答案 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上的索引。