7

更新:より完全な例を示します。

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

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

より良い例の元の質問:

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

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

例えば:

これが 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 を使用しない実装でも問題ありません。

4

2 に答える 2

4

あなたが実際に達成しようとしていることは、あなたの例から私には明らかではありません。条件を満たすノードを除くすべてのノードを取り除いた新しい XML を返しますか? はいの場合、これは MSSQL 2005 に組み込まれているとは思わない XSLT 変換のジョブのように見えます (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つの例でテストしたところ、望ましい結果が得られました。

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

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

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

于 2008-09-18T07:50:42.680 に答える
1

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

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
于 2008-09-18T09:17:48.430 に答える