@SteveChambersの回答に基づいて独自のクエリの実装を開始した後、置換が結果行ごとに 1 回だけ発生することがわかりました。たとえば、OPで言及されているテーブル レコードが与えられた場合、次のクエリは次のようになります。
SELECT
word,
replaceWord,
REGEXP_REPLACE(
'How to find and replace word in text from mysql database?',
CONCAT('(?i)(^|\\W)', word, '(\\W|$)'),
CONCAT('\\1', replaceWord, '\\2')
) AS replaced_text
FROM
words
WHERE
'How to find and replace word in text from mysql database?' REGEXP CONCAT('(?i)(^|\\W)', word, '(\\W|$)');
異なる 3 行の結果が返されます。
word | replaceWord | replaced_text
------+-------------+--------------
text | sentence | How to find and replace letter in text from mysql database?
word | letter | How to find and replace word in sentence from mysql database?
mysql | MySQL | How to find and replace word in text from MySQL database?
各行で 1 つの単語のみが置換されていることに注意してください。
いくつかの議論の後、再帰が必要であるという結論に達しました。次のクエリを使用して、プロシージャまたは関数なしでそれを達成することができました。
SELECT
(@i := @i + 1) AS i,
@tmp := IFNULL(
REGEXP_REPLACE(
@tmp,
CONCAT('(?i)(^|\\W)', word, '(\\W|$)'),
CONCAT('\\1', replaceWord, '\\2')
),
@tmp
) AS replaced_text
FROM
(
SELECT
@tmp := 'How to find and replace word in text from mysql database?',
@i := 0
) x
LEFT JOIN
words
ON
@tmp REGEXP CONCAT('(?i)(^|\\W)', word, '(\\W|$)')
ORDER BY i DESC
LIMIT 1;
このクエリは、元の文字列の各単語を再帰的に置換し、置換を蓄積します。インデックス ( @i
) を使用して行に番号を付けます。最後に、すべての累積置換を含む最後の結果 (より大きなインデックス) のみを返します。
LEFT JOIN
との組み合わせを使用して、IFNULL
置換が行われない場合に元の文字列を返します。