삽입시 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.