2017-01-10 6 views
2

sedと同等の処理をmysqlデータベースのフィールドに対して行う必要があります。フィールドデータはxmlの形式です。SEDとMySQLの対応

本質的には、私は以下の例では{scrubbedvalue}と置き換えて、{sourcevalue}を見つける必要があります。我々は{sourcevalue}の直接の試合はできませんが、それは不明ですが、残りを参照することができます。

これを行うには、簡単にmysqlをそのまま使用する方法がありますか?もしそうでなければ、マッチの開始位置と長さを得るために正規表現を使ってマッチさせる方法がありますか?そのように置き換えますか?

例入力:

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

出力例:データの

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

答えて

1

クレンジングは最高の挿入する前が行われます。

文字列がそれ自体で列にある場合、単純なUPDATEがそのトリックを行います。

MariaDBを使用している場合は、REGEXP_REPLACE()を参照してください。

文字列に埋め込まれている場合は、実際にコードを修正するためにアプリケーション言語を使用する必要があります。

+0

最終クリーニングで元の場所を一意に識別する必要がない場合は、dbダンプに対して 'sed'を実行すれば十分です。私の場合、DevOpsチームによるさらなる操作のために残された一意の「scrubbedvalue」を必要とする上記のようないくつかの場所があります。 MariaDBに関するコメントは好きですが、まだ移行していません。 –

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)[email protected]), 
"{scrubbedvalue}" 
); 

プラス(一致のみ更新レコードへ)REGEXPフィルタ

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

しかし、あなたのXMLチャンクが正規化されていないと異なってフォーマットすることができます場合は、余分な世話をする必要があります(つまり、使用異なる量の空白、エンティティ参照など)。

+0

空白の問題を処理するために 'オプション3'を更新できれば、私はあなたの答えを受け入れます。私は昨日、私の周りに仕事を掲載しました。それはかなりではありませんが、空白を考慮に入れています。 –

+0

@VenomFangs、実際にはすでにある程度「空白になりません」、すなわち です。つまり、「key」属性と「value」属性の前後に任意の数の空白を追加したり、改行を挿入したりすることもできます。 "キー"の後に次の "引用"された値を探し出す(そして相対的な位置を計算するだけでなく)。 – zeppelin

+0

私は数日以内に再検討/テストを行います。すべてが整列すれば、私は受け入れます。ありがとう! –

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'; 
関連する問題