Destruindo dados XML em tabelas
-
17-09-2020 - |
Pergunta
Tenho um problema em que devo fragmentar vários conjuntos de dados XML de vários provedores em um único conjunto de tabelas, mapeando vários elementos nas fontes para minhas próprias tabelas.Posso fazer isso muito bem quando estou coletando informações de nível superior, mas algumas das minhas informações estão em uma coleção, como as categorias.Meu primeiro passo é extrair os dados do XML e colocá-los em algumas tabelas e, em seguida, o próximo passo é mesclar os dados em minhas tabelas reais.
Meus dados XML são assim:
<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>
Quero fragmentar esses dados em uma tabela com ID do produto, ID do item e ID da categoria, quando várias categorias podem ser atribuídas a um único produto
Em primeiro lugar, tenho minha tabela DataDictionary
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
)
Nesta tabela tenho estes registros:
88 Categories product_id int ProviderProductId
89 Categories item_id int ItemId
93 Categories categories/ApiNavCategoryInfo/id int CategoryId
Agora, tenho uma instrução sql que extrai o dicionário de dados do meu provedor e fragmenta os dados em uma tabela.
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
A instrução SQL gerada é semelhante a esta:
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 executo minha instrução, recebo o erro:
XQuery [RawDetails.Data.value()]:'value ()' requer uma singleton (ou sequência vazia), encontrada operando do tipo 'xdt: não tytypedatomic *'
Alguma ideia?
Obrigado.
Solução
Descobri que meus caminhos estavam errados.
eu mudei
Data.nodes('//ArrayOfApiNewItemDetailInfo/ApiNewItemDetailInfo') as NewTable
para
Data.nodes('//ArrayOfApiNewItemDetailInfo/ApiNewItemDetailInfo/categories/ApiNavCategoryInfo') as NewTable
E eu mudei meus registros com isso
88 Categories ../../product_id int ProviderProductId
89 Categories ../../item_id int ItemId
93 Categories id int CategoryId
E isso funcionou.