SQL Server 2005 の XQuery を使用して、特定の属性値を持つノード、またはその属性が欠落しているノードをすべて選択します

StackOverflow https://stackoverflow.com/questions/90023

  •  01-07-2019
  •  | 
  •  

質問

アップデート:より完全な例を挙げます。

提供された最初の 2 つの解決策は、私が言いたかったこととぴったり一致していました。 ない すること。場所が分からないので、ドキュメントツリー全体を見ることができる必要があります。したがって、コンテキストとして /Books/ を指定した次のような解決策は機能しません。

SELECT x.query('.') FROM @xml.nodes('/Books/*[not(@ID) or @ID = 5]') x1(x)

元の質問とより良い例:

SQL Server 2005 の XQuery 実装を使用すると、XML ドキュメント内のすべてのノードを 1 回だけ選択し、元の構造を維持する必要があります。ただし、ノードに特定の属性が欠落している場合、またはその属性に特定の値 (パラメーターによって渡される) がある場合に限ります。また、クエリは、事前定義された深さで選択するのではなく、XML ドキュメント全体 (子孫または自己軸) に対して機能する必要があります。

つまり、個々のノードとその祖先のすべてが属性を欠いている場合、または単一の特定の値を持つ属性を持つ場合にのみ、個々のノードが結果のドキュメントに表示されます。

例えば:

これが XML の場合:

    DECLARE @Xml XML
    SET @Xml =
    N'
<Library>
  <Novels>
    <Novel category="1">Novel1</Novel>
    <Novel category="2">Novel2</Novel>
    <Novel>Novel3</Novel>
    <Novel category="4">Novel4</Novel>
  </Novels>
  <Encyclopedias>
    <Encyclopedia>
      <Volume>A-F</Volume>
      <Volume category="2">G-L</Volume>
      <Volume category="3">M-S</Volume>
      <Volume category="4">T-Z</Volume>
    </Encyclopedia>
  </Encyclopedias>
  <Dictionaries category="1">
    <Dictionary>Webster</Dictionary>
    <Dictionary>Oxford</Dictionary>
  </Dictionaries>
</Library>
    '

カテゴリのパラメータを 1 にすると、次のようになります。

<Library>
  <Novels>
    <Novel category="1">Novel1</Novel>
    <Novel>Novel3</Novel>
  </Novels>
  <Encyclopedias>
    <Encyclopedia>
      <Volume>A-F</Volume>
    </Encyclopedia>
  </Encyclopedias>
  <Dictionaries category="1">
    <Dictionary>Webster</Dictionary>
    <Dictionary>Oxford</Dictionary>
  </Dictionaries>
</Library>

カテゴリのパラメータを 2 にすると、次のようになります。

<Library>
  <Novels>
    <Novel category="2">Novel2</Novel>
    <Novel>Novel3</Novel>
  </Novels>
  <Encyclopedias>
    <Encyclopedia>
      <Volume>A-F</Volume>
      <Volume category="2">G-L</Volume>
    </Encyclopedia>
  </Encyclopedias>
</Library>

XSLT がこの仕事に最適であることはわかっていますが、それは選択肢ではありません。これはすべて SQL Server 2005 で実現する必要があります。完全に T-SQL で実行できる限り、XQuery を使用しない実装でも問題ありません。

役に立ちましたか?

解決

あなたの例からは、実際に何を達成しようとしているのかはわかりません。条件を満たすノードを除いてすべてのノードを取り除いた新しい XML を返しますか?「はい」の場合、これは XSLT 変換のジョブのようですが、MSSQL 2005 には組み込まれていないと思います (UDF として追加できます: http://www.topxml.com/rbnews/SQLXML/re-23872_Performing-XSLT-Transforms-on-XML-Data-Stored-in-SQL-Server-2005.aspx).

ノードのリストを返すだけの場合は、次の式を使用できます。

//Book[not(@ID) or @ID = 5]

しかし、それは必要なものではないという印象を受けます。より明確な例を提供していただけると助かります。

編集:この例は確かにより明確です。私が見つけた最高のものはこれです:

SET @Xml.modify('delete(//*[@category!=1])')
SELECT @Xml

目的は、XML から不要なノードをすべて削除して、元の構造と必要なノードを残すことです。あなたの 2 つの例でテストしたところ、望ましい結果が得られました。

しかし 修正する いくつかの制限があります。select ステートメントでは使用できないようです。データを適切に変更する必要があります。このようなデータを選択で返す必要がある場合は、元のデータをコピーしてそのテーブルを更新する一時テーブルを使用できます。このようなもの:

INSERT INTO #temp VALUES(@Xml)
UPDATE #temp SET data.modify('delete(//*[@category!=2])')

それが役立つことを願っています。

他のヒント

質問があまり明確ではありませんが、これがあなたが探しているものですか?

DECLARE @Xml AS XML
        SET @Xml =
        N'
        <Books>
                <Book ID="1">Book1</Book>
                <Book ID="2">Book2</Book>
                <Book ID="3">Book3</Book>
                <Book>Book4</Book>
                <Book ID="5">Book5</Book>
                <Book ID="6">Book6</Book>
                <Book>Book7</Book>
                <Book ID="8">Book8</Book>
        </Books>
        '
DECLARE @BookID AS INT
SET @BookID = 5
DECLARE @Result AS XML

SET @result = (SELECT @xml.query('//Book[not(@ID) or @ID = sql:variable("@BookID")]'))
SELECT @result
ライセンス: CC-BY-SA帰属
所属していません StackOverflow
scroll top