MySQL 查询仅提取不在字符串中的特定值

MySQL Query to extract only a specific value that not in a string

我有一个数据库列(评论),几乎可以出现任何字母字符、数字或字母数字的组合。在一个例子中,它看起来像这个 55,44,1265,13,​​12 在另一个例子中它可能是 12,55,1265,44,13 也可能是 A45,或 45A 或 ABCDE52JQST 或 12 13 15 或任何东西。

我需要一个 MySQL 查询来根据用户输入的搜索提取任何行。例如,用户可能想要识别其中包含 12 的所有行。不是 1265 不是 12A 只是 12,除 12 之外唯一可接受的值是 ,12 或 12,(逗号 12 或 12 逗号)或数字前后的空格( 12 或 12 )。但不是 1265.

我当前的 where 子句如下所示,虽然它有时有效,但有时无效,即使它每次都有效,它也很难看。我还能如何编写 where 子句来执行我需要的操作,我可以以某种方式使用 perl 表达式吗?请举个例子。

WHERE netID = $netID
            AND
             ( comment LIKE '%$findit' 
            OR comment LIKE '$findit%' 
            
            OR comment = '$findit'
            OR comment = ',$findit'
            OR comment = '$findit,'
            OR comment = ',$findit,'
            
            OR comment LIKE '% $findit '
            OR comment LIKE ' $findit %'
            
            OR comment LIKE '%$findit,'
            OR comment LIKE ',$findit%'
            
            OR comment LIKE '%,$findit'
            OR comment LIKE '$findit,%'
            
            OR comment LIKE '%,$findit '
            OR comment LIKE ' $findit,%'
            
            OR comment LIKE '% $findit'
            OR comment LIKE '$findit %'
            
            OR comment LIKE '%$findit ' 
            OR comment LIKE ' $findit%'
            
            OR comment LIKE '%,$findit,%'
            )

您似乎是用逗号或 spaces 作为分隔符来描述集合数据。我不会进入有关序列化数据存储的典型讲座,而是假设您对此无能为力。

显然,像这样将字符串直接传递到您的 SQL 会带来 SQLi 风险,您应该使用参数化查询或至少对用户输入进行一些可靠的清理和验证。

因此,通过将 space 分隔列表转换为逗号分隔列表来将集合视为集合 -

WHERE FIND_IN_SET('$findit', REPLACE(`comment`, ' ', ',')) > 0

FIND_IN_SET

REPLACE

PREPARED STATEMENTS

更新

Kendle/Bill Karwin 建议的这条 db<>fiddle works for the examples you have provided. Please provide a specific example of value(s) for which this does not work. Using REGEXP 可能是更好的下山路线。

在MYSQL中我们可以使用正则表达式。这里我们使用表达式 (?<![0-9])12(?![0-9]) 表示字符串必须包含 12 并且如果它之前或之后的字符都不能是数字。
我们使用负面回顾和负面展望。

create table base(
val varchar(100));
insert into base values
('55,44,1265,13,12'),
('12,55,1265,44,13'), 
( 'A45, or 45A or '),
(' ABCDE52JQST 1265'),
('12 13 15 or a'),
('123,212, '),
('haza12'),
(1265),
(1212),
(12),
(2012);
select val from base
where val regexp
    '(?<![0-9])12(?![0-9])'
| val              |
| :--------------- |
| 55,44,1265,13,12 |
| 12,55,1265,44,13 |
| 12 13 15 or a    |
| haza12           |
| 12               |

db<>fiddle here