2017-10-23 4 views
1

Ich muss eine Tabelle mit einem XML erstellen.XML zu tsql Select-Anweisung gibt nur eine Zeile zurück

Das ist mein xml:

<root> 
    <Child>c1</Child> 
    <Child>c2</Child> 
    <Child>c3</Child> 
    <Child>c4</Child> 
    <ID>9908</ID> 
</root> 

Mein Versuch:

DECLARE @ixml INT, 
@Param VARCHAR(max)='<root> 
    <Child>c1</Child> 
    <Child>c2</Child> 
    <Child>c3</Child> 
    <Child>c4</Child> 
    <ID>9908</ID> 
</root>' 


EXEC sp_xml_preparedocument @ixml OUTPUT, @Param 

    Select Child,ID 
    FROM OPENXML(@ixml, 'root') 
    WITH 
    (
     Child [nVARCHAR](max) 'Child', 
     ID [INT] 'ID' 
    ) 


---------- 

tatsächliche Ausgang:

Child | ID 
c1  | 9908 

Erwartete Ausgabe:

Child | ID 
c1  | 9908 
c2  | 9908 
c3  | 9908 
c4  | 9908 

kann mir jemand helfen?

+0

würde ich vorschlagen, dass Sie versuchen, nur die "Child" -Elemente auswählen, dann fügen Sie die 'ID', nachdem Sie das Recht – MartinByers

+0

' FROM OPENXML' mit den entsprechenden SPs zur Vorbereitung haben und ein Dokument zu entfernen ist veraltet und sollte nicht mehr verwendet werden. Verwenden Sie stattdessen die entsprechenden [Methoden, die der XML-Datentyp bietet] (https://msdn.microsoft.com/en-us/library/ms190798.aspx). – Shnugo

Antwort

3

Beginnend mit den @Param als XML-Typ deklariert und unter Verwendung von XPath-Ausdrücken in nodes und value, würden Sie erhalten:

DECLARE @Param XML='<root> 
    <Child>c1</Child> 
    <Child>c2</Child> 
    <Child>c3</Child> 
    <Child>c4</Child> 
    <ID>9908</ID> 
</root>' 

SELECT 
    Child=n.v.value('.[1]','NVARCHAR(128)'), 
    ID=n.v.value('../ID[1]','INT') 
FROM 
    @Param.nodes('root/Child') AS n(v); 

mit dem erwarteten Ergebnis.


Eine etwas bessere Version (mit dem Input von @Shnugo) mit direkter Auswahl von /root/ID statt Rückwärtsnavigation im XPath-Ausdruck:

SELECT 
    Child=n.v.value('.[1]','NVARCHAR(128)'), 
    [email protected]('(/root/ID/text())[1]','INT') 
FROM 
    @Param.nodes('root/Child') AS n(v); 
+0

danke .. seine Arbeit –

+2

Gute Antwort, plused es ... Für die Leistung können Sie im Hinterkopf behalten, dass die Rückwärtsnavigation ein Nachteil ist und holen 'Text()' ist etwas schneller als die einfache 'ID [1]' . Ich würde 'SELECT [email protected] ('(/ root/ID/text()) [1]', 'int'), Kind = nvvalue ('text() [1]', 'nvarchar verwenden (128) ') VON ... ' – Shnugo

+0

@Shnugo Vielen Dank für den Hinweis, arbeitete das in meiner Antwort. –

4

Try this:

DECLARE @ixml INT, 
@Param VARCHAR(max)='<root> 
    <Child>c1</Child> 
    <Child>c2</Child> 
    <Child>c3</Child> 
    <Child>c4</Child> 
    <ID>9908</ID> 
</root>' 


EXEC sp_xml_preparedocument @ixml OUTPUT, @Param 

Select Child, ID 
FROM OPENXML(@ixml, '/root/Child') 
WITH 
(
    Child [nVARCHAR](max) '.', ID [int] '../ID' 
) 
+0

danke .. seine Arbeit –

+1

Großartig. Beachten Sie jedoch, dass Sie die XML-Referenz entfernen sollten, wenn Sie fertig sind (exec sp_xml_removedocument @ixml;) – Tyron78

+0

Aufgrund der umständlichen Arbeitsweise mit diesen gespeicherten Prozeduren (einschließlich der Möglichkeit, Dokumente zu schließen usw.) sollten Sie Vermeiden Sie diese und verwenden Sie stattdessen die neue Art der Arbeit mit XML, wie in meiner Antwort beschrieben. –

Verwandte Themen