24 messaggi dal 27 settembre 2012
Ciao a tutti,
Prima di tutto vi spiego la mia situazione:

Ho una tabella xTabella1 che è strutturata in questo modo:
campo1 int, campo2 varchar(80), campo3 xml

il campo3 come potete vedere è un xml e contiene all'interno una struttura variabile in base al record della tabella xTabella1.

Esempio:
nel record1 l'xml è così:

<?xml version="1.0" encoding="utf-8"?>
<TAG1>
  <TAG2>
    <CODICE>ALIM</CODICE>
    <DESCRIZIONE>Alimentatore</DESCRIZIONE>
    <VALORE1>1430</VALORE1>
  </TAG2>
  <TAG2>
    <CODICE>PC</CODICE>
    <DESCRIZIONE>PC</DESCRIZIONE>
    <VALORE1>45464</VALORE1>
  </TAG2>
  <TAG2>
    <CODICE>MTH</CODICE>
    <DESCRIZIONE>MOTHERBOARD</DESCRIZIONE>
    <VALORE1>500</VALORE1>
  </TAG2>
</TAG1>



nel record 2 così:

<?xml version="1.0" encoding="utf-8"?>
<TAG1>
  <TAG2>
    <CODICE>ALIM</CODICE>
    <DESCRIZIONE>Alimentatore</DESCRIZIONE>
    <VALORE1>1430</VALORE1>
    <VALORE2>130</VALORE2>
  </TAG2>
  <TAG2>
    <CODICE>PC</CODICE>
    <DESCRIZIONE>PC</DESCRIZIONE>
    <VALORE1>45464</VALORE1>
    <VALORE2>14730</VALORE2>
  </TAG2>
  <TAG2>
    <CODICE>MTH</CODICE>
    <DESCRIZIONE>MOTHERBOARD</DESCRIZIONE>
    <VALORE1>500</VALORE1>
    <VALORE2>1330</VALORE2>
  </TAG2>
</TAG1>


Come vedete la struttura dell'xml cambia da record a record.
A questo punto mi sono fatto una function in SQL che passandogli come parametro l'id del record mi legge l'elenco dei campi dell'xml, mi costruisce uno statement variabile mettendo come nomi colonna i tag del campo XML e scrivendomi i relativi valori.

Un esempio di ciò che torna la mia funzione passandogli per esempio l'id del record contenente il primo XML di esempio sarà:

CODICE          DESCRIZIONE       VALORE1

ALIM            Alimentatore      1430
PC              PC                45464
MTH             MotherBoard       500


Il mio problema però è che, essendo questa struttura variabile, non posso farmi tornare una TABLE dalla funzione perchè essa deve avere una struttura ben definita, e quindi questa funzione mi esegue semplicemente lo statement che mi sono costruito e me lo fa vedere a video, senza salvarlo da nessuna parte. Siccome devo però mettere questo risultato in join con un'altra tabella ho bisogno che questa funzione mi ritorni una tabella come risultato con la struttura variabile dell'xml.

E' possibile farlo?Come faccio altrimenti a fare join tra questo risultato e un'altra tabella? (la tabella risultante dall'xml ha la stessa struttura della tabella fisica che andrò ad interrogare e a mettere in join, tra l'altro)

Mi va bene qualsiasi soluzione: un'assembly fatto in VB.NET, piuttosto che una stored procedure o una function in SQL, piuttosto che qualsiasi altro modo :-(

Scusate se mi sono dilungato ma non avevo altra possibilità di farvi capire altrimenti.

Grazie anticipatamente!!!

Tutto ciò che non sai è vero!!!
252 messaggi dal 03 novembre 2003
ciao
se ho capito bene, vuoi mettere in join i valori dalle 2 liste XML?
Hai dei file xml da leggere?

Potresti usare direttamente C# con Linq to XML
e fare JOIN (INNER o LEFT JOIN)

ciao

it's not difficult to write, but is difficult write that you mean
24 messaggi dal 27 settembre 2012
No, io ho una tabella con all'interno un campo XML con una struttura che cambia di volta in volta, ma che comunque ha un codice che funge da Primary Key.
Poi ho una tabella fisica che ha una Foreign Key a questo codice.

Devo legare l'XML con una tabella fisica in base alle PK/FK e per farlo ho una funzione che dato l'xml mi costruisce dinamicamente in base alla struttura dell'xml uno statement (query) che eseguito mi restituisce l'xml in 'formato tabellare' per intenderci. Questo risultato io voglio che sia restituito come tabella dalla function solo che per farlo devo sapere a priori la struttura.

Esempio:

CREATE FUNCTION dbo.xGetTableByXml (@Xml xml)
RETURNS @retTable TABLE 
  (
    campo1 CHAR(1) NOT NULL
    , campo2 CHAR(3) NOT NULL
    , campo3 CHAR(7)
                , ....
  )
  AS ...... 


Per farmi tornare quindi una tabella da una funzione in modo poi da fare:

select * from xGetTableByXml(@Xml) inner join TabellaFisica on ....


devo specificargli la struttura a priori che inizialmente non so perchè dipende dall'xml.
Di conseguenza avevo pensato che la ricavo all'interno della funzione creandomi dinamicamente lo statement e di eseguirla e infatti così faccio ma facendo così non ritorna la tabella ma mi da semplicemente a video il risultato.

Non so se mi sono spiegato....è un pò macchinosa forse.

Tutto ciò che non sai è vero!!!
1.976 messaggi dal 27 luglio 2005
Contributi
salve,
se ho ben compreso, ogni riga della tabella contiene un frammento XML destrutturato che puo' contenere N elementi "Valore" contrassegnati da 1 a N;
tu vuoi una restituzione tabellare, per ogni riga, di tutti i subelementi contenuti nel frammento XML.

se questo e' vero, potremmo intraprendere la strada di una ricostruzione tabellare tramite una tradizionale proiezione del frammento xml per poi effettuare un UNPIVOT... devi pero' a priori conoscere la cardinalita' di N al fine di poterla recuperare... nell'esempio di cui sotto, ho "stabilito" che la profondita' sara' da 1 a 4, e ne restituisce, per Valore da 1 a 4 il relativo valore o eventualmente NULL in sua assenza, per poi, nuovamente conoscendo a priori la cardinalita', effettuarne l'UNPIVOT...

fatto questo, ci e' semplice definire una funzione utente che ritorni una tabella per tutte le righe ristrutturate del frammento xml per operare quindi un CROSS APPLY per ogni riga della tabella originale...
il risultato sara' poi facilmente messo in join con le tabelle referenziate relative..

ad esempio,
SET NOCOUNT ON;
USE tempdb;
GO
DECLARE @x1 xml='<TAG1>
  <TAG2>
    <CODICE>ALIM</CODICE>
    <DESCRIZIONE>Alimentatore</DESCRIZIONE>
    <VALORE1>1430</VALORE1>
  </TAG2>
  <TAG2>
    <CODICE>PC</CODICE>
    <DESCRIZIONE>PC</DESCRIZIONE>
    <VALORE1>45464</VALORE1>
  </TAG2>
  <TAG2>
    <CODICE>MTH</CODICE>
    <DESCRIZIONE>MOTHERBOARD</DESCRIZIONE>
    <VALORE1>500</VALORE1>
  </TAG2>
</TAG1>';
DECLARE @x2 xml='<TAG1>
  <TAG2>
    <CODICE>ALIM</CODICE>
    <DESCRIZIONE>Alimentatore</DESCRIZIONE>
    <VALORE1>1430</VALORE1>
    <VALORE2>130</VALORE2>
  </TAG2>
  <TAG2>
    <CODICE>PC</CODICE>
    <DESCRIZIONE>PC</DESCRIZIONE>
    <VALORE1>45464</VALORE1>
    <VALORE2>14730</VALORE2>
  </TAG2>
  <TAG2>
    <CODICE>MTH</CODICE>
    <DESCRIZIONE>MOTHERBOARD</DESCRIZIONE>
    <VALORE1>500</VALORE1>
    <VALORE2>1330</VALORE2>
  </TAG2>
</TAG1>';

PRINT 'SELEZIONE DIRETTA';
SELECT 
  ref.value('CODICE[1]', 'NVARCHAR (20)') AS CODICE,
  ref.value('DESCRIZIONE[1]', 'NVARCHAR (20)') AS DESCRIZIONE,
  ref.value('VALORE1[1]', 'int') AS Valore1,
  ref.value('VALORE2[1]', 'int') AS Valore2,
  ref.value('VALORE3[1]', 'int') AS Valore3,
  ref.value('VALORE4[1]', 'int') AS Valore4
  --, ......
  FROM @x1.nodes('/TAG1/TAG2') xmlData( ref )
  ORDER BY Codice;

PRINT 'UNPIVOTING';
WITH cte AS (
  SELECT 
    ref.value('CODICE[1]', 'NVARCHAR (20)') AS CODICE,
    ref.value('DESCRIZIONE[1]', 'NVARCHAR (20)') AS DESCRIZIONE,
    ref.value('VALORE1[1]', 'int') AS Valore1,
    ref.value('VALORE2[1]', 'int') AS Valore2,
    ref.value('VALORE3[1]', 'int') AS Valore3,
    ref.value('VALORE4[1]', 'int') AS Valore4
    --, ......
    FROM @x1.nodes('/TAG1/TAG2') xmlData( ref )
  )
  SELECT CODICE, DESCRIZIONE, ItemVal
    FROM cte c
    UNPIVOT
    (ItemVal FOR Valore IN (Valore1, Valore2, Valore3, Valore4) ) as tblunpvt;
GO
CREATE TABLE dbo.t ( id int NOT NULL IDENTITY, x xml NOT NULL );
INSERT dbo.t
  VALUES
('<TAG1>
  <TAG2>
    <CODICE>ALIM</CODICE>
    <DESCRIZIONE>Alimentatore</DESCRIZIONE>
    <VALORE1>1430</VALORE1>
  </TAG2>
  <TAG2>
    <CODICE>PC</CODICE>
    <DESCRIZIONE>PC</DESCRIZIONE>
    <VALORE1>45464</VALORE1>
  </TAG2>
  <TAG2>
    <CODICE>MTH</CODICE>
    <DESCRIZIONE>MOTHERBOARD</DESCRIZIONE>
    <VALORE1>500</VALORE1>
  </TAG2>
</TAG1>'),
('<TAG1>
  <TAG2>
    <CODICE>ALIM</CODICE>
    <DESCRIZIONE>Alimentatore</DESCRIZIONE>
    <VALORE1>1430</VALORE1>
    <VALORE2>130</VALORE2>
  </TAG2>
  <TAG2>
    <CODICE>PC</CODICE>
    <DESCRIZIONE>PC</DESCRIZIONE>
    <VALORE1>45464</VALORE1>
    <VALORE2>14730</VALORE2>
  </TAG2>
  <TAG2>
    <CODICE>MTH</CODICE>
    <DESCRIZIONE>MOTHERBOARD</DESCRIZIONE>
    <VALORE1>500</VALORE1>
    <VALORE2>1330</VALORE2>
  </TAG2>
</TAG1>');
GO
CREATE FUNCTION dbo.ufn_UnpivotArticle (
  @Id int  
  ) 
  RETURNS @ret TABLE 
  (
    Id int,
    CODICE nvarchar(20),
    DESCRIZIONE nvarchar(20),
    ItemVal int
  )
AS BEGIN
  DECLARE @x xml;
  SELECT @x = x
    FROM dbo.t
    WHERE Id =  @Id;

  WITH cte AS (
    SELECT
      ref.value('CODICE[1]', 'NVARCHAR (20)') AS CODICE,
      ref.value('DESCRIZIONE[1]', 'NVARCHAR (20)') AS DESCRIZIONE,
      ref.value('VALORE1[1]', 'int') AS Valore1,
      ref.value('VALORE2[1]', 'int') AS Valore2,
      ref.value('VALORE3[1]', 'int') AS Valore3,
      ref.value('VALORE4[1]', 'int') AS Valore4
      --, ......
      FROM @x.nodes('/TAG1/TAG2') xmlData( ref )
    )
    INSERT INTO @ret
      SELECT @Id AS Id, CODICE, DESCRIZIONE, ItemVal
      FROM cte c
        UNPIVOT
        (ItemVal FOR Valore IN (Valore1, Valore2, Valore3, Valore4) ) as tblunpvt;
    RETURN
END;
GO
SELECT t.id
  , ca.CODICE, ca.DESCRIZIONE, ca.ItemVal
  FROM dbo.t t CROSS APPLY dbo.ufn_UnpivotArticle (t.id) ca
  WHERE t.id = 1

SELECT t.id
  , ca.CODICE, ca.DESCRIZIONE, ca.ItemVal
  FROM dbo.t t CROSS APPLY dbo.ufn_UnpivotArticle (t.id) ca
  ORDER BY t.id;

GO
DROP FUNCTION dbo.ufn_UnpivotArticle;
DROP TABLE dbo.t;
--<--------
SELEZIONE DIRETTA
CODICE               DESCRIZIONE          Valore1     Valore2     Valore3     Valore4
-------------------- -------------------- ----------- ----------- ----------- -----------
ALIM                 Alimentatore         1430        NULL        NULL        NULL
MTH                  MOTHERBOARD          500         NULL        NULL        NULL
PC                   PC                   45464       NULL        NULL        NULL

UNPIVOTING
CODICE               DESCRIZIONE          ItemVal
-------------------- -------------------- -----------
ALIM                 Alimentatore         1430
PC                   PC                   45464
MTH                  MOTHERBOARD          500

id          CODICE               DESCRIZIONE          ItemVal
----------- -------------------- -------------------- -----------
1           ALIM                 Alimentatore         1430
1           PC                   PC                   45464
1           MTH                  MOTHERBOARD          500

id          CODICE               DESCRIZIONE          ItemVal
----------- -------------------- -------------------- -----------
1           ALIM                 Alimentatore         1430
1           PC                   PC                   45464
1           MTH                  MOTHERBOARD          500
2           ALIM                 Alimentatore         1430
2           ALIM                 Alimentatore         130
2           PC                   PC                   45464
2           PC                   PC                   14730
2           MTH                  MOTHERBOARD          500
2           MTH                  MOTHERBOARD          1330



se, invece, non ho compreso niente, allora.... :)
saluti

Andrea Montanari
http://www.hotelsole.com - http://www.hotelsole.com/asql/index.php
24 messaggi dal 27 settembre 2012
Ok perfetto allora provo a seguire il tuo consiglio!!!!Grazie mille per la risposta molto approfondita e spero di non averti fatto perdere troppo tempo.

Grazie ancora

Tutto ciò che non sai è vero!!!

Torna al forum | Feed RSS

ASPItalia.com non è responsabile per il contenuto dei messaggi presenti su questo servizio, non avendo nessun controllo sui messaggi postati nei propri forum, che rappresentano l'espressione del pensiero degli autori.