MySQL - 在全文搜索中转义&符号(&)

时间:2014-06-16 07:35:06

标签: mysql escaping full-text-search

我们正在使用全文搜索来搜索公司名称,一切顺利,直到我们的公司名称为&符号,例如'M&安培; S'。

SELECT name FROM company WHERE MATCH (name) against ('M&S' IN BOOLEAN MODE);

由于MySQL将&符号视为布尔运算符,因此无法返回任何结果。需要布尔模式,因此不能简单地关闭它。

我正在寻找的是一种逃避&符号的方法,以便MySQL正确处理它并找到记录。

放弃全文搜索以支持LIKE s也不是一个选项

感谢您的帮助

3 个答案:

答案 0 :(得分:5)

似乎&似乎不是您用于全文搜索的排序规则中的单词字符。

因此您必须创建自己的排序规则(或重新编译MySQL服务器),将&添加到我在MySQL文档中找到的单词字符列表中( http://dev.mysql.com/doc/refman/5.0/en/fulltext-fine-tuning.html):

  

如果要更改被视为单词的字符集   字符,您可以通过多种方式完成此操作,如中所述   以下列表。进行修改后,您必须重建   包含任何FULLTEXT索引的每个表的索引。假设   您希望将连字符(' - ')视为单词字符。   使用以下方法之一:

     

修改MySQL源:在myisam / ftdefs.h中,查看true_word_char()   和misc_word_char()宏。添加' - '到其中一个宏和   重新编译MySQL。

     

修改字符集文件:这不需要重新编译。该   true_word_char()宏使用“字符类型”表来区分   来自其他角色的字母和数字。 。您可以编辑内容   其中一个字符集XML文件中的数组   指定' - '是一个“字母。”然后使用给定的字符集   你的FULLTEXT索引。有关阵列的信息   格式,请参见第10.3.1节“字符定义数组”。

     

为索引列使用的字符集添加新的排序规则,   并更改列以使用该排序规则。一般信息   有关添加排序规则的信息,请参见第10.4节“将排序规则添加到   字符集”。有关特定于全文索引的示例,请参阅   第12.9.7节“为全文索引添加排序规则”。

更新:如果您使用的是latin1排序规则,请打开位于mysql/share/charsets/latin1.xml的XML文件。并在地图中找到相应的字符代码 - 在这种情况下,您可以将地图用于小写或大写,因为这对于&符号无关紧要:

<lower>
<map>
 00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F
 10 11 12 13 14 15 16 17 18 19 1A 1B 1C 1D 1E 1F
 20 21 22 23 24 25 26 27 28 29 2A 2B 2C 2D 2E 2F
 30 31 32 33 34 35 36 37 38 39 3A 3B 3C 3D 3E 3F
 40 61 62 63 64 65 66 67 68 69 6A 6B 6C 6D 6E 6F
 70 71 72 73 74 75 76 77 78 79 7A 5B 5C 5D 5E 5F
 60 61 62 63 64 65 66 67 68 69 6A 6B 6C 6D 6E 6F
 70 71 72 73 74 75 76 77 78 79 7A 7B 7C 7D 7E 7F
 80 81 82 83 84 85 86 87 88 89 8A 8B 8C 8D 8E 8F
 90 91 92 93 94 95 96 97 98 99 9A 9B 9C 9D 9E 9F
 A0 A1 A2 A3 A4 A5 A6 A7 A8 A9 AA AB AC AD AE AF
 B0 B1 B2 B3 B4 B5 B6 B7 B8 B9 BA BB BC BD BE BF
 E0 E1 E2 E3 E4 E5 E6 E7 E8 E9 EA EB EC ED EE EF
 F0 F1 F2 F3 F4 F5 F6 D7 F8 F9 FA FB FC FD FE DF
 E0 E1 E2 E3 E4 E5 E6 E7 E8 E9 EA EB EC ED EE EF
 F0 F1 F2 F3 F4 F5 F6 F7 F8 F9 FA FB FC FD FE FF
</map>
</lower>
&符号的&符号为U+0026,并且在utf-8中对0x26进行编码,因此在地图中搜索26 - 这是第3个第7栏。第

然后在ctype - 地图中将字符的类型从10改为,这意味着标点符号为01,这意味着小写字母:

<ctype>
<map>
 00
 20 20 20 20 20 20 20 20 20 28 28 28 28 28 20 20
 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20
 48 10 10 10 10 10 01 10 10 10 10 10 10 10 10 10
 84 84 84 84 84 84 84 84 84 84 10 10 10 10 10 10
 10 81 81 81 81 81 81 01 01 01 01 01 01 01 01 01
 01 01 01 01 01 01 01 01 01 01 01 10 10 10 10 10
 10 82 82 82 82 82 82 02 02 02 02 02 02 02 02 02
 02 02 02 02 02 02 02 02 02 02 02 10 10 10 10 20
 10 00 10 02 10 10 10 10 10 10 01 10 01 00 01 00
 00 10 10 10 10 10 10 10 10 10 02 10 02 00 02 01
 48 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10
 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10
 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01
 01 01 01 01 01 01 01 10 01 01 01 01 01 01 01 02
 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02
 02 02 02 02 02 02 02 10 02 02 02 02 02 02 02 02
</map>
</ctype>

重新启动MySQL服务器,相应的排序规则正在处理&,就像是一封小写字母。

当然最好首先复制并重命名新的排序规则XML - 文件,并复制并粘贴Index.xml中的相应行(不要忘记在XML标记中使用新的未使用的ID,并将其链接到新的排序规则XML - 文件,这样您就不会丢失原始排序规则。

您可以在此处找到我从中获取大部分信息的完整文档: http://dev.mysql.com/doc/refman/5.0/en/full-text-adding-collation.html

注意 - 对于使用Mysql 5.7版本的所有人,请使用未使用的排序规则ID。 mysql文章http://dev.mysql.com/doc/refman/5.0/en/fulltext-fine-tuning.html适用于Mysql 5.5版本。要获得最大归类ID,请使用以下查询 -

   SELECT MAX(ID) FROM INFORMATION_SCHEMA.COLLATIONS;

答案 1 :(得分:0)

编辑:所以&amp;将它分成两个单独的单词......因为它们是1个字母,所以它不会返回任何内容。我用&#34; Ma&amp; Sa&#34; ...我的ft_min_word_len = 4进行了测试...它没有返回任何内容,因为该字符串的长度&gt; 4但它没有返回它必须将它分成两个单词...看起来像northkildonan所做的建议是你必须做的。

所以这可能是也可能不是答案..但我希望这有助于解决这个问题。试试这个。

首先:运行此语句 - SHOW VARIABLES LIKE 'ft_min_word_len';并确认长度实际上是= 2 如果是,我不确定它与长度超过4的单词的区别是什么

第二:我这样做了并得到了结果。

设置:

我在localhost数据库上设置了一个示例表...

create table company(
`id` int,
`name` varchar(55)
);

insert into company
(`id`, `name`)
values
(1, 'oracle'),
(2, 'microsoft'),
(3, 'M&S'),
(4, 'dell');

<强>测试: 当ft_min_word_len = 4时测试,显然它没有返回任何东西。

SELECT `name` FROM company WHERE MATCH (`name`) against ("M&S" IN BOOLEAN MODE);

我不想尝试重新启动我的localhost数据库,将长度重置为2(因为我经常使用它,所以我不小心搞了一些东西)..

但是我想到了试图寻找一个长度超过4的公司的名称与&amp;在它。

更多设置:

insert into company
(`id`, `name`)
values
(5, 'Mary&Sasha');

另一项测试:

SELECT `name` FROM company WHERE MATCH (`name`) against ("Mary&Sasha" IN BOOLEAN MODE); 

这返回了http://screencast.com/t/Rx8mh98OUp

我也这样做只是因为整理正在弄乱它,但我怀疑这是问题..

COLLATION STUFF:

ALTER TABLE company MODIFY
    `name` VARCHAR(55)
      CHARACTER SET latin1
      COLLATE latin1_german2_ci;

您还可以使用以下方法检查表格排序规则:

SHOW TABLE STATUS;

希望这至少是一些帮助:)

答案 2 :(得分:-1)

&不是mysql中的特殊字符,因此您可以存储和搜索表达式& 您可以按照以下方式测试

    SELECT name FROM  `testing` WHERE name LIKE  '%&%'

还请尝试使用以下内容替换&

    SET @searchstring = 'M&S';
    SET @searchstring = REPLACE(@searchstring,'&','&amp;');
    SELECT name FROM company WHERE MATCH (name) against (@searchstring IN BOOLEAN MODE);


你也可以看一下regexp。 http://dev.mysql.com/doc/refman/5.1/en/regexp.html
在这里&amp;如下使用。

    mysql> SELECT '&' REGEXP '[[.ampersand.]]';


以下查询也为您提供结果

    SELECT * 
    FROM  `testing` 
    WHERE  `name` REGEXP CONVERT( _utf8 'M&S'
    USING latin1 ) COLLATE latin1_german2_ci 
    LIMIT 0 , 30

请同时阅读这篇帖子,也许你能比我理解得更好。这是SQL,但它们似乎解决了这个问题 http://forums.asp.net/t/1073707.aspx?Full+text+search+and+sepcial+characters+like+ampersand+

抱歉,我无法提供更多帮助