2017-11-21 5 views
2

SQL Serverテーブルのフィールドからデータを取得しようとしています。これはxmlとして保存され、別の行に各ノードの値を取得したかったのです。 XMLサンプルは、このようなものです:xmlデータを含むストアドプロシージャ

<id>{a75f61ce-6627-489f-83bb-d03fc880b764}</id> 
<rows> 
    <row> 
     <columns> 
      <column name="ec_date" value="15-November-2017" type="System.DateTime" /> 
      <column name="ec_amount" value="160" type="System.Decimal" /> 
      <column name="ec_description" value="viaje en coche" type="System.String" /> 
      <column name="ec_factura" value="0" type="System.String" /> 
      <column name="ec_item" value="105.01" type="System.String" /> 
      <column name="DefaultKey" value="1" type="System.Int32" /> 
     </columns> 
    </row> 
    <row> 
     <columns> 
      <column name="ec_date" value="16-November-2017" type="System.DateTime" /> 
      <column name="ec_amount" value="2.55" type="System.Decimal" /> 
      <column name="ec_description" value="2 horas de parkin" type="System.String" /> 
      <column name="ec_factura" value="0" type="System.String" /> 
      <column name="ec_item" value="15.04" type="System.String" /> 
      <column name="DefaultKey" value="2" type="System.Int32" /> 
     </columns> 
    </row> 
    <row> 
     <columns> 
      <column name="ec_date" value="17-November-2017" type="System.DateTime" /> 
      <column name="ec_amount" value="200" type="System.Decimal" /> 
      <column name="ec_description" value="taxi a burgos" type="System.String" /> 
      <column name="ec_factura" value="0" type="System.String" /> 
      <column name="ec_item" value="15.06" type="System.String" /> 
      <column name="DefaultKey" value="3" type="System.Int32" /> 
     </columns> 
    </row> 
</rows> 

誰かがそれぞれ異なる列値を持つSQL行の各<行>要素を取得する方法を教えてもらえますか?

はすべて

+1

このXMLの構築があなたの管理下にある場合は、日付( 'yyyy-MM-dd'または' yyyy-MM-ddTHH:mm:ss')にISO8601を使用することを強くお勧めします。あなたのフォーマットは文化と言語に依存し、すべての内部テストに合格するかもしれませんが、* 12月とDezemberのような小さな違いのために顧客のシステムを壊す* – Shnugo

答えて

3

表にXml列を解析するためには、あなたは、XQueryを使用することをお勧めします、ありがとうございました。ここでは、このことについて行くだろう方法の例だ - それはrow xml要素ごとに1行を返します。

SELECT 
    Rows.col.value('(column[@name="ec_date"]/@value)[1]', 
     'DATE') AS EcDate, 
    Rows.col.value('(column[@name="ec_amount"]/@value)[1]', 
     'decimal(10,2)') AS EcAmount, 
    Rows.col.value('(column[@name="ec_description"]/@value)[1]', 
     'varchar(max)') AS EcDescription 
    -- .. etc 
FROM 
    MyTable mt 
    CROSS APPLY 
     mt.XmlCol.nodes('//rows/row/columns') 
     AS Rows(col); 

(column[@name="ec_date"]/@value)[1]は緩く「私に値ec_datename属性を持つ最初の列要素を見つけて、私返すように変換しますvalue属性の値。

With a Sql Fiddle here

必須警告

xml columnの属性名と型は一貫しているように見えますが、データに型システムが埋め込まれていると思われます。つまり、列の型を動的に変更する機能を提供しようとすると、 XML文書内のすべてのデータの一方

は、強力なスキーマを持っている、そして私は、XMLは、データモデリングのためのお粗末な選択であることを主張するだろう - それ自身のテーブルにrowを正規化しているともっと良かったはず。 Xmlは冗長な形式であり、スキーマを繰り返す(つまり、スペースを浪費する)ため、解析やフィルタリングが難しい場合があります。

+0

'行と列の間に1対1の関係があるので、 、[xml data](http://sqlfiddle.com/#!6/cbc48/2)の複数の行があっても。私はエイリアシングでラッパー '行'を呼び出す自由を取ったと思う。 – StuartLC

+1

申し訳ありませんが、あなたはもちろんです!あなたは 'Xpath'で'/xml'を使っていますが、質問の元のXMLはルートノードを表示していません。間違っているかもしれません... – Shnugo

+0

良い点 - OPの元の文書にはルートがなく、技術的に有効ではありませんが、XQueryのように見えます。更新しました。 – StuartLC

1

私はすべての最初の<id>{a75f61ce-6627-489f-83bb-d03fc880b764}</id>を削除し、あなたがOPENXML

DECLARE @idoc int, @doc varchar(MAX) 

SET @doc='<id>{a75f61ce-6627-489f-83bb-d03fc880b764}</id> 
<rows> 
    <row> 
     <columns> 
      <column name="ec_date" value="15-November-2017" type="System.DateTime" /> 
      <column name="ec_amount" value="160" type="System.Decimal" /> 
      <column name="ec_description" value="viaje en coche" type="System.String" /> 
      <column name="ec_factura" value="0" type="System.String" /> 
      <column name="ec_item" value="105.01" type="System.String" /> 
      <column name="DefaultKey" value="1" type="System.Int32" /> 
     </columns> 
    </row> 
    <row> 
     <columns> 
      <column name="ec_date" value="16-November-2017" type="System.DateTime" /> 
      <column name="ec_amount" value="2.55" type="System.Decimal" /> 
      <column name="ec_description" value="2 horas de parkin" type="System.String" /> 
      <column name="ec_factura" value="0" type="System.String" /> 
      <column name="ec_item" value="15.04" type="System.String" /> 
      <column name="DefaultKey" value="2" type="System.Int32" /> 
     </columns> 
    </row> 
    <row> 
     <columns> 
      <column name="ec_date" value="17-November-2017" type="System.DateTime" /> 
      <column name="ec_amount" value="200" type="System.Decimal" /> 
      <column name="ec_description" value="taxi a burgos" type="System.String" /> 
      <column name="ec_factura" value="0" type="System.String" /> 
      <column name="ec_item" value="15.06" type="System.String" /> 
      <column name="DefaultKey" value="3" type="System.Int32" /> 
     </columns> 
    </row> 
</rows>' 

-- delete <id> 
SET @doc=STUFF(@doc,1,47,'')  

EXEC sp_xml_preparedocument @idoc OUTPUT, @doc; 

SELECT * 
FROM OPENXML(@idoc,'/rows/row/columns',2) 
    WITH (ec_date  date   './column[1]/@value', 
     ec_amount  float  './column[2]/@value', 
     ec_description varchar(200) './column[3]/@value', 
     ec_factura  int   './column[4]/@value', 
     ec_item  float  './column[5]/@value', 
     DefaultKey  int   './column[6]/@value'); 

EXEC sp_xml_removedocument @idoc; 
GO 

を使用することができると思います。

+0

'FROM OPENXML'と対応するSPを用意して文書を削除することは古くなっており、もう使用しないでください。むしろ適切な[XMLデータ型が提供するメソッド](https://msdn.microsoft.com/en-us/library/ms190798.aspx)を使用してください。 – Shnugo

+0

@ Shnugo - ありがとうございました!私はXMLに関する知識をリフレッシュする必要があります。私はそれを長い間働いていません。 – Leran2002

関連する問題