2017-01-10 1 views
2

필드 데이터가 xml 형식 인 mysql 데이터베이스의 필드에 대해 sed과 동등한 작업을 수행해야합니다.MySQL 용 SED와 같습니다.

아래의 예에서 본질적으로 {sourcevalue}을 찾아 {scrubbedvalue}으로 바꿔야합니다. {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}"' 
); 

옵션 # 2 당신이 중 하나를 (예를 들어, 당신은 MySQL의 이전 버전을 실행하는) 작동하지 않는 경우, 당신은 원시 사용하려고 할 수 있습니다

3 문자열 조작 함수를 사용하여 같은 결과를 얻습니다.:

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}" 
); 

플러스

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

그러나 당신이 당신의 XML 덩어리가 정상화되지 않고 다른 포맷 할 수있는 경우 각별히주의해야합니다 (일치하는 경우에만 레코드를 업데이트까지) REGEXP 필터 (즉, 사용 다른 공백, 엔티티 참조 등).

+0

공백 문제를 처리하기 위해'Option 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'; 
관련 문제