Столкнулся с этим неожиданным поведением при написании кода для синтаксического анализа; -ограниченные списки в столбце SQL.
На этом этапе я заменяю только случаи, которые окружены разделителями, чтобы избежать ложные срабатывания. Без разделителей замена «Алиса» в «Алиса; Боб; Алиса; Алиса в стране чудес; Чарль ie» приведет к «Боб; в стране чудес; Чарль ie».
Код для воспроизведения:
SELECT REPLACE('Alice;Alice;Alice;Alice;Alice;Alice',';Alice;',';Bob;')
Это 6 повторений Алисы, 4 из которых окружены разделителями. Ожидаемый результат:
Alice;Bob;Bob;Bob;Bob;Alice
Фактический результат:
Alice;Bob;Alice;Bob;Alice;Alice
Почему 3-й и 5-й Алисы не были заменены?
Моя теория такова, что когда REPLACE находит "; Алиса;» во второй позиции он «резервирует» этот блок текста, так что следующий, 3-й «; Алиса;», который перекрывается со 2-м на один символ, недоступен для ЗАМЕНЫ в качестве совпадения. Логично, потому что ЗАМЕНА первого найденного события может заменить его на что-либо вообще; например, если он заменил его на "# Alice #", тогда 3-й "; Alice;" теперь будет "#Alice;" - нет совпадения.
В этом случае REPLACE фактически не меняет ";" разделяется 2-м и 3-м экземплярами: но внутренне функция REPLACE осторожна и просто перемещается за последний символ 2-й Алисы. И то же самое происходит с 4-м и 5-м вхождениями.
Обходной путь - обернуть ЗАМЕНУ в WHILE, пока строка поиска больше не будет найдена.
У кого-нибудь есть лучшее объяснение или обходной путь