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

MySQL选择查询,第二个字符的数字范围为0到9,mysql,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) ; 但是,当我改变查询以这样缩短它时,它给出的字符串包含我不想要的字母表

我想从表中选择数据,第一个字符为
*
,第二个字符的数字为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在此查询中不能按预期使用中间字符?

您会看到此问题,因为MySQL将尝试将非数字字符转换为整数,然后再将其与0和10进行比较。由于MySQL的强制转换规则,非数字字符串始终被视为等于零,因此0和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]
    后跟一个数字
如果在
之间的
中使用带引号的字符串,则可以使用您的方法并避免强制转换,如在
中(子字符串(msgbody,2,1)在“0”和“9”之间)


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

你把事情复杂化了。在这种情况下,如果你说

要从第一个字符为*且第二个字符的数字为0到9的表中选择数据

那么您需要从“*0…”到“*9…”的所有内容

所以你想

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

其中MyColumn>='*0'和SUBSTR(MyColumn,1,2)='*0'和MyColumn这两种方法都有效。为什么您更喜欢
REGEXP
方法?我在哪里可以找到MySQL的强制转换规则?您的REGEXP代码给出了一个复制运算符-操作数错误。
'replication-operator-operator-invalid'
,因此我将代码放在括号中,现在正在工作。示例-MyColumn REGEXP'(^\\\*[0-9])|(^\\*[0-9])用于选择第一个字符为*且第二个或第三个字符为数字的条目。请把你的答案更正一下,我会把你的答案标记为正确的answer@user20152015我在5.6中进行了测试,在我的原始模式中没有这样的错误。重复运算符错误可能是由于您添加了
|
,是的,在这种情况下需要
()
@user20152015。如果您想将第二个或第三个字符作为数字,则不需要
|
替换,因为
匹配零个或一个字符。它可以是
REGEXP'^\\\*.[0-9]'
包含在第二个位置,并消除
()
。这将匹配第二个或第三个数字。@Michael,REGEXP方法不使用索引,而substring方法使用索引。因此,regexp方法会给出误报,而substring方法不会。所以,在这种情况下,我更喜欢子字符串方法。
WHERE MyColumn >= '*0' AND SUBSTR(MyColumn, 1, 2) <= '*9';
WHERE MyColumn >= '*0' AND MyColumn <= '*9ZZZZZZZZ'
WHERE MyColumn >= '*0' AND MyColumn <= '*:'