给定一个表“更新”,其中包含由两个字段组成的记录,两个字段均仅包含文本:
existing_value
和 replacement_value
此表用于更新带有单个字段的第二个表“主”:
name
其中
name
字段将更新为 replacement_value
,用 existing_value
替换 replacement_value
的所有实例。然而,所需要的并不是在 main.name = updates.repleacement_value
的基础上替换“主”表的简单更新,其中 main.name = updates.existing_value
。
main.name
、updates.existing_value
和updates.replacement_value
都包含采用简单值形式的字符串,例如Joe
,或者它们可以(并且大多数情况下)包含包含分隔符的字符串,以分隔单个字段中保存的多个值例如Joe Soap\\Joe Bloggs\\Joe
(是的,我知道字段填充是一个糟糕的主意,但源数据就是这样)。
为了澄清起见,我们假设一个适用以下内容的示例:
updates.existing_value = 'Joe'
updates.replacement = 'Jose'
Main 有两条记录:
main.name = 'Joe Soap\\Joe Bloggs\\Joe'
main.name = 'Joe\\Joe Soap\\Joe\\Joe Little'
我需要解决的问题是仅将每条记录中独立的
'Joe'
替换为'Jose'
,而不会无意中影响“Joe Soap”,“Joe Bloggs”或“Joe Little”。
解决该问题的一种方法是将“main”中的每条记录加载到Python中,将每个记录转换为一个列表,处理列表并重新编译字符串,然后将其写回“main”(数据帧将是最有效的),但在走这条路之前,我想知道是否有办法直接在 SQLite 中实现相同的目的?
我已经尝试过
LIKE
、INSTR()
和 REPLACE()
,但似乎没有办法缩小 REPLACE()
的范围,因为它将用 ' 替换 'Joe' 的所有实例何塞'.
是否有其他一些我没有考虑过的
SQL
方法,或者问题最好在外部解决还是SQLite
?
您可以分隔搜索词:
update main
set name =
trim(
replace(
replace(
replace(
'\'||name||'\',
'\',
'\\'
),
'\'||map.old||'\',
'\'||map.new||'\'
),
'\\',
'\'
),
'\'
)
from (
select distinct
main.rowid as id,
updates.existing_value as old,
updates.replacement as new
from main inner join updates
where instr(
'\'||main.name||'\',
'\'||updates.existing_value||'\'
)
) as map
where main.rowid = map.id;
\Joe\
Joe\Joe\Joe
)existing_value
注: 如果多个更新应用于同一行,则结果是非确定性。