相当于MySQL的SED

时间:2017-01-10 20:14:17

标签: mysql regex sed

我需要对mysql数据库中的字段执行相当于sed的操作,字段数据的格式为xml。

从本质上讲,我需要在下面找到{sourcevalue},并在下面的示例中将其替换为{scrubbedvalue}。我们不能在{sourcevalue}上进行直接匹配,因为它是未知的,但其余的可以被引用。

有没有一种简单的方法可以使用mysql开箱即用?如果没有,有没有办法通过正则表达式匹配来获得匹配的起始位置和长度,并以这种方式替换?

示例输入:

<Attributes>
  <Map>
    ...
    <entry key="foo" value="{sourcevalue}"/>
    ...
  </Map>
</Attributes>

示例输出:

<Attributes>
  <Map>
    ...
    <entry key="foo" value="{scrubbedvalue}"/>
    ...
  </Map>
</Attributes>

3 个答案:

答案 0 :(得分:1)

最好在插入之前完成清理数据。

如果字符串本身在一列中,那么一个简单的UPDATE就可以了。

如果您使用的是MariaDB,请参阅REGEXP_REPLACE()

如果它隐藏在一个字符串中,你真的应该使用一些应用程序语言来修复代码。

答案 1 :(得分:1)

AFAIK Mysql不提供简单的“RegExp查找和替换”功能。

但是还有其他一些方法可以解决手头的问题:

选项#1

通过添加新的数据库表来规范化您的数据模式,例如: “属性”,带有“键”和“值”列,并将数据放入其中,而不是将其保留在XML“blob”中。

通过这种方式,您将能够使用常规SQL语法来查询和更新属性,并在必要时对其进行正确索引。

选项#2

如果#1不适合您(无论出于何种原因), 您可以尝试使用新的(Mysql 5.7+)XML functions,如下所示:

SELECT @xml:='<Attributes>
  <Map>
    <entry key="a" value="a"/>
    <entry key="foo" value="{sourcevalue}"/>
    <entry key="z" value="z"/>
  </Map>
</Attributes>';

SELECT UpdateXML(
@xml,
'//entry[@key="foo"]/@value',
'value="{scrubbedvalue}"'
);

选项#3

如果#2对你不起作用(例如你正在运行旧版本的Mysql),你可以尝试使用原始字符串操作函数来实现相同的结果,例如:

SELECT @key:='foo';

SELECT 
REPLACE(
@xml,
SUBSTRING(
 @xml,
 @s:=LOCATE('"',@xml,LOCATE(CONCAT('key="',@key,'"'),@xml)+LENGTH(@key)+6)+1,
 LOCATE('"',@xml,@s+LENGTH(@key)+6)-@s),
"{scrubbedvalue}"
);

加上REGEXP过滤器(仅更新匹配的记录)

WHERE @xml REGEXP 'key="foo"';

但是如果你的XML块没有规范化并且可以采用不同的格式(即使用不同数量的空格,实体引用e.t.c。),你将不得不格外小心。

答案 2 :(得分:1)

出于文档目的,昨天我在等待答案时做了以下操作。

这不是很漂亮,可能会被改造成更干净的东西,但如果一切都失败了,它应该适用于其他人。

我本质上得到值的左侧,值的右侧,然后与新值连接并将其更新到db。

UPDATE mytable SET attributes = 
        CONCAT(
                -- length of 'value="' is 7. Want 7-1 == 6
                SUBSTRING(attributes, 1, LOCATE('value="', attributes, POSITION('foo' in attributes))+6), -- Left of value
                '%%SCRUBBED_VALUE%%', -- Scrubbed value.
                -- length of 'value="' is 7. Want 7 for next " reference.
                SUBSTRING(attributes, LOCATE('"', attributes, LOCATE('value="', attributes, POSITION('foo' in attributes))+7), LENGTH(attributes) - LOCATE('"', attributes, LOCATE('value="', attributes, POSITION('foo' in attributes))+7) + 1) -- Right of Value
        )
WHERE name = 'SomeUniqueIdentifier';