2010-09-22 4 views
6

Ich versuche, eine Tabelle in eine XML-Struktur umzuwandeln, und eine der Spalten in meiner Tabelle soll einen übergeordneten Knoten und die andere Spalte einen untergeordneten Knoten darstellen.SQL-Tabelle in XML mit Spalte als übergeordnetem Knoten transformieren

Ich habe einen Teil des Weges, aber ich habe nicht die komplette Lösung. Ich brauche die Spalte TABLE_NAME, die in einen übergeordneten XML-Knoten transformiert werden soll, und die Spalte COLUMN_NAME, die als untergeordnete Knoten transformiert werden soll. Wenn ich Folgendes ausführe, bekomme ich die Verschachtelung, aber ich bekomme auch mehrere Elternknoten.

select 
TABLE_NAME AS 'tn', 
COLUMN_NAME AS 'tn/cn' 
from (
select 'TABLE_A' AS TABLE_NAME, 'COLUMN_1' AS COLUMN_NAME 
UNION ALL 
select 'TABLE_A' AS TABLE_NAME, 'COLUMN_2' AS COLUMN_NAME 
UNION ALL 
select 'TABLE_B' AS TABLE_NAME, 'COLUMN_1' AS COLUMN_NAME 
UNION ALL 
select 'TABLE_B' AS TABLE_NAME, 'COLUMN_2' AS COLUMN_NAME 
) x 
for xml path(''), ROOT('datatable') 

OUPUT >>>

<datatable> 
    <tn>TABLE_A<cn>COLUMN_1</cn></tn> 
    <tn>TABLE_A<cn>COLUMN_2</cn></tn> 
    <tn>TABLE_B<cn>COLUMN_1</cn></tn> 
    <tn>TABLE_B<cn>COLUMN_2</cn></tn> 
</datatable> 

SOLL OUTPUT >>>

<datatable> 
    <TABLE_A> 
    <cn>COLUMN_1</cn> 
    <cn>COLUMN_2</cn> 
    </TABLE_A> 
    <TABLE_B> 
    <cn>COLUMN_1</cn> 
    <cn>COLUMN_2</cn> 
    </TABLE_B> 
</datatable> 

Ist das möglich oder träume ich? und ist es möglich, ohne XML EXPLICIT oder ist das die Art von etwas, für das EXPLICIT da ist?

Die andere Möglichkeit, die ich versucht habe, ist, das xml zu stopfen und dann eine xquery anzuwenden, aber keine Freude damit noch.

Danke,

Gary

+0

@Gary, welcher Dialekt von SQL (Ora Cle, SQLServer, MySQL usw.) benutzen Sie? Einige von ihnen haben Dialekt-spezifische Erweiterungen für die Handhabung von XML. –

+0

Hallo Mark, ich benutze die M $ SQL Server 2008 R2, Standard Edition –

+2

Haben Sie erwogen, in XML zu exportieren und dann eine XSL-Transformation darauf auszuführen? –

Antwort

3

Wie andere erwähnt haben, erlaubt FOR XML nicht, Knoten dynamisch zu benennen. Die Knotennamen müssen Konstanten sein, wenn die Abfrage selbst kompiliert wird. Sie können dies mit dynamischen SQL umgehen, aber dann endet mit Code, der immer schwerer zu lesen wird.

Eine Alternative wäre, manuell die talbe Namen Knoten und CAST in XML zu generieren:

Setup:

CREATE TABLE a (table_name VARCHAR(20), column_name VARCHAR(20) 
INSERT INTO a VALUES ('TABLE_A', 'COLUMN_1') 
INSERT INTO a VALUES ('TABLE_A', 'COLUMN_2') 
INSERT INTO a VALUES ('TABLE_B', 'COLUMN_1') 
INSERT INTO a VALUES ('TABLE_B', 'COLUMN_2') 

Execute:

SELECT CAST(
     '<' + table_name + '>' 
    + (SELECT c.column_name as 'CN' 
     FROM a c 
     WHERE c.table_name = p.table_name 
     FOR XML PATH('')) 
    + '</' + table_name + '>' 
    AS XML) 
    FROM a p 
GROUP BY p.table_name 
FOR XML PATH(''), ROOT('datatable') 

Produziert:

<datatable> 
    <TABLE_A> 
    <CN>COLUMN_1</CN> 
    <CN>COLUMN_2</CN> 
    </TABLE_A> 
    <TABLE_B> 
    <CN>COLUMN_1</CN> 
    <CN>COLUMN_2</CN> 
    </TABLE_B> 
</datatable> 
2

Es ist möglich, müssen Sie Spalten mit Pfad nennen. So: 'parent\child'.

Versuchen Sie folgendes:

select 
( 
select * from (
    select 'COLUMN_1' 'cn' 
    UNION ALL 
    select 'COLUMN_2' 'cn' 
) as t 
for xml path(''), root('TABLE_A'), type 
) 
,( 
select * from (
    select 'COLUMN_1' 'cn' 
    UNION ALL 
    select 'COLUMN_2' 'cn' 
) as t 
for xml path(''), root('TABLE_B'), type 
) 
for xml path(''), ROOT('datatable') 
+0

Entschuldigung, ich brauche eine Produktionslösung, die mit großen Tabelleneingaben arbeitet, ohne dass man Dinge wie root ('TABLE_A') fest programmieren muss. –

+0

Je mehr ich darüber nachdenke, desto mehr denke ich, dass es nicht getan werden kann. Ich möchte, dass die Daten in meiner ersten Spalte die Knotennamen und die Daten in meiner zweiten Spalte die Knotenwerte darstellen. –

+0

@ sqlconsumer.net Sie können jede Art von XML als Varchar erstellen und dann als xml –

3

Leider - was Sie versuchen, nicht möglich zu tun ist. Zwei Hauptprobleme (wenn Sie einen Spielraum haben, könnte es eine Lösung geben).

Erstens ist, dass keine der XML-Optionen in SQL (nicht einmal mit EXPLICIT) dynamische Benennung von Knoten ermöglichen. Sie können entweder ein Attribut <tn id="TABLE_A" /> oder einen Wert <tn>TABLE_A</tn> verwenden, aber Sie können <TABLE_A> nicht erhalten, wenn Sie es nicht fest codieren.

XML-Typen ermöglichen Verschachtelung/Unterabfragen.

SELECT V1.tbname 
,(SELECT V2.colname FROM testtable V2 
    WHERE V1.tbname = V2.tbname FOR XML PATH(''), ELEMENTS, TYPE) 
FROM testtable V1 
FOR XML AUTO, ROOT('datatable') 

Ihr zweites Problem kommt von der Tatsache, dass Ihre Daten denormalisiert sind. Es gibt keine Möglichkeit, eine eindeutige Liste von Tabellen zu erhalten (Sie können DISTINCT nicht verwenden, da SQL XML-Typen nicht vergleichen kann). Dies begrenzt, was Sie in einem einzigen "Pass" (Anweisung) tun können.

Wenn Sie eine temporäre Tabelle (oder Tabellenvariable) verwenden möchten, können Sie eine eindeutige Liste von Tabellennamen auswählen und diese mit Spaltennamen wie im Beispiel verbinden (führen Sie die folgenden zuerst aus und ersetzen Sie die äußeren durch mit @ tblist).

DECLARE @tblist TABLE (tbname varchar(20)) 
INSERT INTO @tblist SELECT DISTINCT tbname FROM testtable 

Es gibt diese:

<datatable> 
    <V1 tbname="TBA"> 
    <colname>COL 1</colname> 
    <colname>COL 2</colname> 
    </V1> 
    <V1 tbname="TBB"> 
    <colname>COL 1</colname> 
    <colname>COL 2</colname> 
    </V1> 
</datatable> 

Sie würden auch bereit sein müssen, um Ihre Tabellennamen Knoten Attribute haben sein (man immer einen GREP laufen konnte oder einfach ersetzen danach den Knoten machen bewertet) Es wäre nahe, wenn nicht genau das Format, das Sie suchen.

Entschuldigung - das ist wahrscheinlich nicht das, was Sie hören möchten. Aber in ein paar einfachen Schritten kann es getan werden. Nur nicht direkt aus SQL Server in einer einzigen Anweisung.

Verwandte Themen