4

XML フィールドを複数列のデータセットに「分割」したいと考えています。XML は次のようになります。

<simple>
    <propertyid>
        <value>p1</value>
        <value>p2</value>
        <value>p3</value>
        <value>p4</value>
    </propertyid>
    <complexid>
        <value>c1</value>
        <value>c2</value>
        <value>c3</value>
    </complexid>
</simple>

私はそのようなことをしようとしました (TSQL で XML を扱うたびに、私のコードは間違っていると感じます):

;WITH source AS (
    SELECT CAST(@xmlstring AS XML) AS x
)
SELECT 
    items.item.query('.')
FROM source
CROSS APPLY x.nodes('/simple/*/value') AS items(item)

予想されるデータセット:

ColumnName      Value
------------------------
propertyid      p1
propertyid      p2
propertyid      p3
propertyid      p4
complexid       c1
complexid       c2
complexid       c3

どうすれば必要な結果を得ることができますか? T-SQL + XML + XQuery の説明とサンプルで良いリソースをお勧めできますか?

4

3 に答える 3

5

次のようなものを試してください。

;WITH source AS (
    SELECT CAST(@xmlstring AS XML) AS x
)
SELECT
    ColumnName = XTbl.Parent.value('local-name(.)', 'varchar(50)'),
    [Value] = XTbl2.ChildValues.value('(.)[1]', 'varchar(20)')
FROM source
CROSS APPLY
    x.nodes('/simple/*') AS XTbl(Parent)
CROSS APPLY
    XTbl.Parent.nodes('value') AS XTbl2(ChildValues)

これはあなたのために働きますか?私の場合、(ヘルパーテーブルを使用して)目的の出力が得られます。

このSQLフィドルをデモとして見る

于 2012-12-18T11:28:50.237 に答える
3

そして、これが1 CROSS APPLYを使用した私自身のソリューションです。

;WITH source AS (
    SELECT CAST(@xmlstring AS XML) AS x
)
SELECT
    items.item.value('local-name(..)', 'varchar(300)') AS ColumnName,
    items.item.value('text()[1]', 'varchar') AS Value
FROM source
CROSS APPLY x.nodes('/simple/*/value') AS items(item)

主に親ノードへのアクセスに失敗し、'../local-name()' を使用しようとしましたが、local-name() は名前を表示するために XPath を必要とします。その後、親ノード名を表示すると簡単になります。

于 2012-12-18T11:32:28.450 に答える
1

XQueryソリューションの提案をリクエストしたので、次のようになります。

declare function local:createTestDoc() as node()* {
    <simple>
        <propertyid>
            <value>p1</value>
            <value>p2</value>
            <value>p3</value>
            <value>p4</value>
        </propertyid>
        <complexid>
            <value>c1</value>
            <value>c2</value>
            <value>c3</value>
        </complexid>
    </simple>
};

declare function local:doProcessing($arg as node()*) as xs:string* {
    let $simpleElement := $arg

    return (
        concat("ColumnName", "    ", "Value")
        ,
        for $propertyId in $simpleElement/propertyid/*
        return (
            concat("propertyid", "    ", data($propertyId))
        )
        ,
        for $complexId in $simpleElement/complexid/*
        return (
            concat("complexid", "    ", data($complexId))
        )
    )
};

local:doProcessing(local:createTestDoc())

local:createTestDoc()を使用する代わりに、次のようなものを使用してドキュメントを含める必要があります。

declare variable $myDoc := doc("urlToDoc");

そしてそれをlocal:doProcessing()fnに渡します。

local:doProcessing($myDoc)
于 2012-12-18T23:20:58.330 に答える