使用另一个表中的数据查找并替换MySQL中的字符串

时间:2010-03-24 17:13:59

标签: sql mysql

我有两个MySQL表,我想在另一个中使用数据查找和替换文本字符串。

texts

+---------------------+
|      messages       |
+---------------------+
| 'thx guys'          |
| 'i think u r great' |
| 'thx again'         |
| ' u rock'           |
+---------------------+

dictionary

+--------------+---------------+
| bad_spelling | good_spelling |
+--------------+---------------+
|    'thx'     |    'thanks'   |
|    ' u '     |    ' you '    |
|    ' r '     |    ' are '    |
+--------------+---------------+

我希望SQL能够查看消息中的每一行,并用good_spelling替换bad_spelling的每个实例,并为所有bad_spelling和good_spelling对执行此操作。

我最接近的是:

update texts, dictionary
set texts.message = replace(texts.message,
                            dictionary.bad_spelling,
                            dictionary.good_spelling)

但这只会将“thx”更改为“thanks”(两行),并且不会继续将“u”替换为“you”或将“r”替换为“are”。

如何使它在replace语句中使用字典中的所有行?


PS忘记提到这是一个小例子,在真实的情况下我会有很多查找/替换对,这可能会随着时间的推移而增加。

4 个答案:

答案 0 :(得分:1)

我从未使用过MySql,所以这只是一个基于我的其他数据库工作的理论。在阅读其他答案时,尝试使用REPLACE(),我想我可以发布这个并让一个有MySql语法经验的人有一些想法来制定基本解决方案。

这里有一些SQL Server代码可以完成大部分工作:

DECLARE @Source table (Texts varchar(50))
INSERT @Source VALUES ('thx guys')
INSERT @Source VALUES ('i think u r great')
INSERT @Source VALUES ('thx again')
INSERT @Source VALUES ('u rock')

DECLARE @Dictionary table (bad_spelling varchar(50), good_spelling varchar(50))
INSERT @Dictionary VALUES ('thx', 'thanks')
INSERT @Dictionary VALUES ('u', 'you')
INSERT @Dictionary VALUES ('r', 'are')

SELECT
    t.Texts,COALESCE(d.good_spelling,c.ListValue) AS WordToUse
    FROM @Source                                     t
        CROSS APPLY dbo.FN_ListToTable(' ',t.Texts)  c
        LEFT OUTER JOIN @Dictionary                  d ON c.ListValue=d.bad_spelling

输出:

Texts              WordToUse
------------------ ---------
thx guys           thanks
thx guys           guys
i think u r great  i
i think u r great  think
i think u r great  you
i think u r great  are
i think u r great  great
thx again          thanks
thx again          again
u rock             you
u rock             rock

(11 row(s) affected)

在上面的查询中使用“真正的”PK比使用实际的“文本”更好,但OP不会在该表中列出很多列,所以我使用“文本”。

使用SQL Server,您需要使用一些时髦的XML语法将行重新连接在一起(因此我不会显示该代码,因为它无关紧要),但是使用MySql的GROUP_CONCAT()您应该能够将单词行连接在一起成为短语行。

(SQL Server)拆分函数的代码及其工作原理可以在这里找到:SQL Server: Split operation

答案 1 :(得分:0)

你必须在文字上多次调用替换:

Update ...
Set texts.message = Replace(
                        Replace(
                            Replace( texts.message, 'thx ', 'thanks ' )
                            , ' u ', ' you ')
                        , ' r ', ' are ')

编辑鉴于您说您有多次替换,您需要在具有多个UPDATE语句调用的游标中执行此操作。类似的东西(我根本没有测试过,所以要小心):

Create Temporary Table ReplaceValues 
    (
    BeforeText varchar(100) not null
    , AfterText varchar(100) not null
    )

Insert ReplaceValues(BeforeText, AfterText) Values('thx ', 'thanks ')
Insert ReplaceValues(BeforeText, AfterText) Values(' u ', ' you ')
Insert ReplaceValues(BeforeText, AfterText) Values(' r ', ' are ')

DECLARE done int DEFAULT(0)
DECLARE BeforeValue varchar(100);
DECLARE AfterValue varchar(100);
DECLARE CONTINUE HANDLER FOR NOT FOUND SET done = 1;

DECLARE ReplaceList CURSOR FOR Select BeforeText, AfterText From ReplaceValues;

OPEN ReplaceList;   

REPEAT
    If NOT done THEN
        FETCH ReplaceList INTO BeforeValue, AfterValue;

        Update texts
        Set texts.message = REPLACE(texts.message, BeforeValue, AfterValue);
    END IF  
UNTIL done END REPEAT;
CLOSE ReplaceList;

您可以将所有这些包装到一个程序中,以便以后再次调用它。

答案 2 :(得分:0)

它并不是一直都是因为即使替换已经运行了x次(其中x是字典中的行数),只保留一个更新(最后一个)。

交易不会记下中间结果,因此无法将其视为下一批替换的输入值。

As(AFAIK)MySQL不支持递归查询,你不得不采用程序方法。

答案 3 :(得分:0)

无论如何,您需要多次执行查询。由于这是clean-up类型的操作,您通常偶尔会这样做,我建议您执行以下查询,直到有更新的内容。我不知道如何使用MySql,但在SQL Server中,它将检查更新的行数(这是UPDATE查询执行的结果),然后运行再次UPDATE,直到没有更新行。

update  texts, 
        dictionary
set     texts.message = replace(texts.message, dictionary.bad_spelling, dictionary.good_spelling)
where   texts.message <> replace(texts.message, dictionary.bad_spelling, dictionary.good_spelling)