1

特定の文字列要素と数値要素に xsi:nil="true" を含む XML があります。次に例を示します。

declare @data xml

set @data = '<?xml version="1.0" encoding="utf-8"?>
             <collection xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
              <item>
               <stringprop1>foo</stringprop1>
               <stringprop2 xsi:nil="true" />
               <decimalprop3 xsi:nil="true" />
              </item>
             </collection>'

SQL Server 2008 R2 でその XML を照会したいと考えています。私は OPENXML を使用していますが、10 進数型ではうまく機能しません。書きたいコードは次のとおりです。

declare @doc int
exec sp_xml_preparedocument @doc OUTPUT, @data;

select 
  stringprop1,
  stringprop2,
  decimalprop3  
from openxml(@doc, '/collection/item', 2)
with
(
  stringprop1 nvarchar(50)
  ,stringprop2 nvarchar(50)
  ,decimalprop3 decimal(18, 5)
)

exec sp_xml_removedocument @doc;

これは、nvarchar を 10 進数に変換することについて文句を言います。いくつかハッキングした後、私はこれにたどり着きました:

exec sp_xml_preparedocument @doc OUTPUT, @data;

select 
  nullif(stringprop1, '') as stringprop1,
  nullif(stringprop2, '') as stringprop2,
  convert(decimal(18, 5), nullif(decimalprop3, '')) as decimalprop3
from openxml(@doc, '/collection/item', 2)
with
(
  stringprop1 nvarchar(50)
  ,stringprop2 nvarchar(50)
  ,decimalprop3 nvarchar(50)
)

exec sp_xml_removedocument @doc;

どちらでもいいと思います。しかし、xsi:nil が NULL を意味し、文字列だけでなく 10 進数でも問題ないことを OPENXML に伝える方法はありますか?

4

3 に答える 3

2

xsi:nil は XML スキーマ機能であり、OpenXML はそれが存在する前に設計されており、xsi:nil をサポートしていません。SQL Server 2008 を使用しているため、これを機能させる 1 つの方法は次のとおりです。

  1. データを検証し、xsi:nil を認識して空の値にマップする適切な XML スキーマで XML を制約します。

  2. nodes() および value() メソッドを使用してデータを抽出します。

敬具マイケル

于 2011-06-09T10:03:31.623 に答える
1

これは行う必要があります:

@doc int
exec sp_xml_preparedocument @doc OUTPUT、@data、'<row xmlns:xsi ="http://www.w3.org/2001/XMLSchema-instance"/>'を宣言します

選択する  
    stringprop1、
    stringprop2、
    decimalprop3
openxmlから(@doc、'/ collection / item'、2)
と
((
    stringprop1 nvarchar(50)、
    stringprop2 nvarchar(50)'stringprop2 [not(@xsi:nil = "true")]'、
    decimalprop3 nvarchar(50)'decimalprop3 [not(@xsi:nil = "true")]'
)。

exec sp_xml_removedocument @doc;
于 2012-05-08T16:21:33.880 に答える
0

ネクロマンシング。
これは私のために働くものです:

-- How to create the XML 
/*
DECLARE @xml XML 
SET @xml = ( SELECT (SELECT * FROM T_Benutzer FOR XML PATH('row'), ROOT('table'),  ELEMENTS xsinil) AS outerXml )

-- SELECT @xml 
*/


DECLARE @xml xml 
SET @xml = '<table xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
  <row>
    <PLK_UID>7CA68E6E-E998-FF92-BE70-126064765EAB</PLK_UID>
    <PLK_Status>1</PLK_Status>
    <BLA_UID>00000000-0000-0000-0000-000000000000</BLA_UID>
  </row>
  <row>
    <PLK_UID>C8A19BB1-6B45-67A6-0417-1F455EE8D2E1</PLK_UID>
    <PLK_Status>1</PLK_Status>
    <BLA_UID xsi:nil="true" />
  </row>
  <row>
    <PLK_UID>C8A19BB1-6B45-67A6-0417-1F455EE8D2E2</PLK_UID>
    <PLK_Status xsi:nil="true" />
    <BLA_UID xsi:nil="true" />
  </row>
  <row>
    <PLK_UID>C8A19BB1-0000-67A6-0417-1F455EE8D2E3</PLK_UID>
    <PLK_Status xsi:nil="true" />
    <BLA_UID>C8A19BB1-1111-67A6-0417-1F455EE8D2E1</BLA_UID>
  </row>
  <row>
    <PLK_UID>C8A19BB1-0001-67A6-0417-1F455EE8D2E4</PLK_UID>
    <PLK_Status>666</PLK_Status>
    <BLA_UID>C8A19BB1-1112-67A6-0417-1F455EE8D2E1</BLA_UID>
  </row>
</table>'


DECLARE @handle INT  
DECLARE @PrepareXmlStatus INT  

EXEC @PrepareXmlStatus = sp_xml_preparedocument @handle OUTPUT, @XML

SELECT 
     PLK_UID 
    ,PLK_Status 
    ,BLA_UID
FROM OPENXML(@handle, '/table/row', 2) WITH 
(
     PLK_UID uniqueidentifier 'PLK_UID[not(@*[local-name()="nil" and . ="true"])]' 
    ,PLK_Status int  'PLK_Status[not(@*[local-name()="nil" and . ="true"])]' 
    ,BLA_UID uniqueidentifier  'BLA_UID[not(@*[local-name()="nil" and . ="true"])]' 
)  

WHERE (1=1) -- AND

EXEC sp_xml_removedocument @handle 

フィールドリストの作成方法:

SELECT 
      CASE WHEN ORDINAL_POSITION = 1 THEN N'     ' ELSE N'    ,' END 
    + N'"' + COLUMN_NAME 
    + N'" '  
    + 
    CASE 
        WHEN DATA_TYPE = 'nvarchar' THEN N'national character varying' 
        WHEN DATA_TYPE = 'varchar' THEN N'character varying' 
        ELSE DATA_TYPE 
    END 
    + 
    CASE 
        WHEN DATA_TYPE IN ('char', 'nchar', 'binary') THEN 
                  N'(' 
                + CAST(CHARACTER_MAXIMUM_LENGTH AS nvarchar(36)) 
                + N')' 
        WHEN DATA_TYPE IN ('varchar', 'nvarchar', 'varbinary') THEN 
                N'(' + 
                CASE WHEN CHARACTER_MAXIMUM_LENGTH = -1 THEN 'MAX' ELSE CAST(CHARACTER_MAXIMUM_LENGTH AS nvarchar(36)) END 
                + N')' 
        WHEN DATA_TYPE IN ('datetimeoffset', 'datetime2', 'time', 'smalldatetime') THEN 
                  N'(' 
                + CAST(DATETIME_PRECISION AS nvarchar(36)) 
                + N')' 
        WHEN DATA_TYPE IN ('decimal', 'numeric') THEN 
                  N'(' 
                + CAST(NUMERIC_PRECISION AS nvarchar(36)) 
                + N',' 
                + CAST(NUMERIC_SCALE AS nvarchar(36)) 
                + N')' 

        ELSE N'' -- N'(default)' 
    END 
    + ' ''' + COLUMN_NAME + '[not(@*[local-name()="nil" and . ="true"])]''' 
FROM INFORMATION_SCHEMA.COLUMNS 
WHERE TABLE_SCHEMA = 'dbo' 
AND TABLE_NAME = 'T_Benutzer' 
ORDER BY ORDINAL_POSITION 
于 2019-06-17T13:56:46.193 に答える