Triturazione di dati XML in tabelle
-
17-09-2020 - |
Domanda
Ho un problema in cui devo brandire più set di dati XML da più fornitori in un singolo set di tabelle mappando vari elementi nelle fonti alle mie tabelle. Posso farlo bene solo quando raccogliamo le informazioni di alto livello, ma alcune delle mie informazioni sono in una collezione, come le categorie. Il mio primo passo è solo per estrarre i dati fuori da XML e inserirlo in poche tabelle e quindi il passo successivo è unire i dati nelle mie tabelle reali.
I miei dati XML sembrano questo:
<ArrayOfApiNewItemDetailInfo>
<ApiNewItemDetailInfo>
<categories>
<ApiNavCategoryInfo>
<count></count>
<id></id>
<name></name>
<selected></selected>
</ApiNavCategoryInfo>
<ApiNavCategoryInfo>
<count></count>
<id></id>
<name></name>
<selected></selected>
</ApiNavCategoryInfo>
</categories>
<item_id></item_id>
<product_id></product_id>
</ApiNewItemDetailInfo>
<ArrayOfApiNewItemDetailInfo>
.
Voglio brandire questi dati in una tabella con ID prodotto, ID elemento e ID di categoria, quando possono essere assegnate più categorie a un singolo prodotto
Prima di tutto, ho il mio tavolo Datadtionary
CREATE TABLE [dbo].[DataDictionary](
[Id] [int] IDENTITY(1,1) NOT NULL,
[Provider] [varchar](50) NOT NULL,
[XmlColumn] [varchar](100) NOT NULL,
[Datatype] [varchar](100) NOT NULL,
[DestinationColumn] [varchar](100) NOT NULL
)
.
In questa tabella ho questi record:
88 Categories product_id int ProviderProductId
89 Categories item_id int ItemId
93 Categories categories/ApiNavCategoryInfo/id int CategoryId
.
Ora, ho un'istruzione SQL che tira nel dizionario dei dati per il mio provider e brandisce i dati in una tabella.
CREATE TABLE #SQLWork (Row_Id INT IDENTITY,SQL varchar(500))
INSERT #SQLWork (SQL) VALUES ('DROP TABLE TempCategories')
INSERT #SQLWork (SQL) VALUES ('SELECT ')
INSERT #SQLWork (SQL) SELECT 'Categories.value(''' + XmlColumn + '[1]''' + ',''' + Datatype + ''') as ' + DestinationColumn + ', '
FROM DataDictionary WHERE UPPER(Provider) = 'CATEGORIES'
UPDATE #SQLWork SET SQL = REPLACE(SQL,', ','') WHERE row_id = @@IDENTITY
INSERT #SQLWork (SQL) VALUES (' INTO TempCategories ')
INSERT #SQLWork (SQL) VALUES (' FROM RawDetails CROSS APPLY Data.nodes(''' + '//ArrayOfApiNewItemDetailInfo/ApiNewItemDetailInfo' + ''') as NewTable(Categories)')
DECLARE @SQL nvarchar(max)
select @SQL = coalesce(@SQL + ' ',' ') + Sql from #SQLWork Order By Row_Id
--SELECT @SQL
exec sp_executesql @sql
drop table #Sqlwork
.
L'istruzione SQL che viene generata è simile:
DROP TABLE TempCategories
SELECT
Categories.value('product_id[1]','int') as ProviderProductId,
Categories.value('item_id[1]','int') as ItemId,
Categories.value('categories/ApiNavCategoryInfo/id[1]','int') as CategoryId
INTO
TempCategories
FROM
RawDetails
CROSS APPLY
Data.nodes('//ArrayOfApiNewItemDetailInfo/ApiNewItemDetailInfo') as NewTable(Categories)
.
Quando eseguo la mia dichiarazione, ottengo l'errore:
.xquery [rawdetails.data.value ()]: 'Valore ()' richiede un singleton (o Sequenza vuota), trovato operando di tipo 'XDT: UNTYREPATOMIC *'
Qualche idea?
Grazie.
Soluzione
Ho scoperto che i miei percorsi erano sbagliati.
Ho cambiato
Data.nodes('//ArrayOfApiNewItemDetailInfo/ApiNewItemDetailInfo') as NewTable
.
a
Data.nodes('//ArrayOfApiNewItemDetailInfo/ApiNewItemDetailInfo/categories/ApiNavCategoryInfo') as NewTable
.
E ho cambiato i miei record con questo
88 Categories ../../product_id int ProviderProductId
89 Categories ../../item_id int ItemId
93 Categories id int CategoryId
.
e quello ha funzionato.