我有两个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忘记提到这是一个小例子,在真实的情况下我会有很多查找/替换对,这可能会随着时间的推移而增加。
答案 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)