삽입시 SQL 서버가 XML 구조를 변경 함


15

SQL Server의 XML 열에 일부 XML 데이터를 삽입하고 있지만 데이터가 삽입 된 후 SQL Server에 의해 변경되었습니다. 여기에 내가 삽입 한 데이터가 있습니다

              <xsl:value-of select="name/n/given" />
            <xsl:text> </xsl:text>
          <xsl:value-of select="name/n/family" />

다시 읽으면 다음과 같습니다

              <xsl:value-of select="name/n/given" />
          <xsl:text />
          <xsl:value-of select="name/n/family" />

두 번째 줄에주의하십시오. XSLT 변환 출력 방법을 변경하기 때문에 문제가됩니다. 첫 번째 예는 이름과 성 사이에 공백을 만드는 반면 두 번째 예는 공백을 만들지 않으므로 JohnJohnsen과 같고 첫 번째는 John Johnsen과 같습니다.

이 문제를 해결할 방법이 있습니까?


XSLT 변환 출력 방법이 변경되므로 문제가됩니다. 첫 번째 줄은 이름과 성 사이에 공백을 만들지 만 두 번째 줄은 사이에 공백을 만들지 않으므로 JohnJohnsen과 같을 것입니다. 첫 번째 줄은 John Johnsen과 같습니다
— Mr Zach

hmhm, 적절한 공간 ""이지만이 주석과 같은 공간이 아닙니다 (볼 수 없음)
— a_vlad

1
데이터에 존재하지 않는 제어 문자 (예 : _또는 ~)를 사용하여 프레젠테이션시 공백으로 대체 할 수 있습니다.
— Aaron Bertrand

답변:


25

xml:space = "preserve"공간을 유지하려는 노드에서 사용할 수 있습니다 . xml : space를 사용하는 것은 "의도의 신호일뿐" 이지만 SQL 서버는 우리에게 친절합니다.

하나의 노드

declare @X xml =
'<root>
  <element xml:space = "preserve"> </element>
  <element> </element>
</root>'

select @X;

결과:

<root>
  <element xml:space="preserve"> </element>
  <element />
</root>

전체 문서 :

declare @X xml =
'<root xml:space = "preserve">
  <element> </element>
  <element> </element>
</root>'

select @X;

결과:

<root xml:space="preserve">
  <element> </element>
  <element> </element>
</root>

전체 문서의 다른 옵션은 스타일 1로 변환 을 사용 하는 것입니다 .

중요하지 않은 공백을 유지하십시오. 이 스타일 설정은 xml : space = "preserve"의 동작과 일치하도록 기본 xml : space 처리를 설정합니다.

declare @X xml = convert(xml, 
'<root>
  <element> </element>
  <element> </element>
</root>', 1)

select @X;

이것이 필요하다는 것이 흥미 롭습니다. "중요하지 않은"공백을 결정하고 문서를 수정하지 않고 자동으로 제거하는 것은 SQL Server의 일이 아닙니다.
— Monica와의 가벼움 경주

3
@LightnessRacesinOrbit SQL Server의 구현에 매우 만족합니다. XML로 형식화 (공백)는 말할 때까지 중요하지 않은 것으로 간주됩니다. 실제로이 문서에있는 노드 수와 스토리지 크기에
— Mikael Eriksson

3
여기서는 데이터를 XML로 받아 들여 XML로 저장하고 조작하거나 변형하지 않고 단순히 문서를 저장하는 것 이외의 다른 형태의 XML 레이어 셰 나니 건을 가지고 있기 때문에 (위상 적으로) 동작 때문에 스펙 위반으로 간주합니다. "애플리케이션"이 아닌 "프로세서"에 속하므로 공백을 제거해서는 안됩니다 .
— Monica와의 가벼움 경주

9

이 SQL Server 설명서의 페이지 에는

데이터는 내부 XML 형식으로 저장됩니다. 중요하지 않은 공백, 속성 순서, 네임 스페이스 접두사 및 XML 선언과 같은 정보는 유지되지 않기 때문에 텍스트 XML의 동일한 사본이 아닐 수 있습니다.

귀하의 예에서는 중간 태그의 공백이 중요하지 않은 것으로 간주하여 표현을 자유롭게 리팩터링 할 수 있다고 가정합니다. 나는 이것에 대한 해결책이 없다고 생각한다. SQL Server가 XML 데이터 형식을 구현하는 방식입니다.

해결 방법에는 @Aaron이 말한 것처럼 공백 대신 자리 표시자를 사용하는 것이 포함됩니다. 소비자는 이러한 토큰을 삽입하고 제거해야합니다. 또는 열을 XML 대신 nvarchar로 정의하십시오. 이렇게하면 모든 공백과 다른 서식이 확실히 유지됩니다. 간단한 예 :

create table x(i nvarchar(99), j xml);
insert x values ('<a> </a>', '<a> </a>');  -- note the space
select * from x

i           j
----------  -------
<a> </a>    <a />  

nvarchar 열은 입력 형식을 유지하지만 XML 열은 유지하지 않습니다.

SQL 쿼리에서 XPATH를 사용할 수 없게됩니다. XML이 응용 프로그램에서만 파쇄 된 경우 이것은 중요하지 않습니다. 또한 문자열이 중요한 경우 DB의 공간을 절약하여 압축 할 수 있습니다.


중요하지 않은 공간에 대한 히트 (또는 누락)에 의존하지 않는 한 XML 형식을 다시 지정하더라도 XML 버전에 대한 쿼리에서 XPATH를 계속 사용할 수 있습니다.
— Aaron Bertrand

0

CDATA데이터를 저장할 때 공간을 감쌀 수 있습니다 .

<xsl:text><![CDATA[ ]]></xsl:text>

그런 다음 SQL Server는 공간을 내부적으로 유지하지만을 CDATA사용하여 결과를 다시 가져올 때 불필요한 마크 업을 제거하는 것으로 보입니다 SELECT. 다행히도 SELECT다음 과 같은 결과를 다시 사용할 때 공간이 유지됩니다 .

DECLARE @X XML = '<text><![CDATA[ ]]></text>'
DECLARE @Y XML

SET @Y = (SELECT @X)

SELECT @Y

결과는 다음과 같습니다.

<text> </text>

또한 CDATA를 시도했지만 제거되었습니다.
— Mr Zach

@MrZach CDATA 자체는 제거되었지만 공간은 남아 있습니다. (SQL Express 2016
— Bruno

이상하게 여기 공간이 제거되었습니다. 2016 년이나 2017 년을 표현하십시오
— Mr Zach Zach
당사 사이트를 사용함과 동시에 당사의 쿠키 정책과 개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.