Cette requête devrait vous aider à démarrer.
La clé est de détruire votre fichier XML. Mais puisque vous insérez dans une table avec une IDENTITÉ, vous devez utiliser des "clés naturelles" pour revenir à la "clé de substitution IDENTITY". Donc, tant que votre "codFilial" (que j'appelle le "codFilialNaturalKey") est une contrainte unique, vous serez en mesure de revenir sur cela pour faire correspondre le PK de la table parente au FK de la table des enfants.
J'ai fait quelques colonnes de données pour vous (ce qui signifie aussi que je n'ai pas fait toutes les colonnes pour vous). Et ajouté des éléments "item" supplémentaires pour montrer que cela fonctionne pour plusieurs "items".
Il existe également un convertisseur DataTime DateTime (UDF). Vous voudrez tirer votre valeur en tant que varchar et ALORS l'exécuter à travers le UDF pour convertir en un DateTime.
IF OBJECT_ID('tempdb..#DestinationCupomVendaParentTable') IS NOT NULL
begin
drop table #DestinationCupomVendaParentTable
end
IF OBJECT_ID('tempdb..#DestinationItemCupomVendaChildTable') IS NOT NULL
begin
drop table #DestinationItemCupomVendaChildTable
end
CREATE TABLE #DestinationCupomVendaParentTable
(
CupomVendaParentSurrogateIdentityKey int not null identity (1001, 1),
codFilialNaturalKey int,
tipoVenda int
)
CREATE TABLE #DestinationItemCupomVendaChildTable
(
DestinationChildSurrogateIdentityKey int not null identity (3001, 1),
CupomVendaParentSurrogateIdentityKeyFK int,
numeroDoItemNaturalKey int,
codigoDoProduto int
)
-- Declare XML variable
DECLARE @data XML;
-- Element-centered XML
SET @data = N'
<listaCupons xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<cupomVenda>
<codFilial>123456</codFilial>
<dtVenda>2013-01-01T00:00:00</dtVenda>
<numeroDePdv>0.000000000000000</numeroDePdv>
<cupomFiscal>12345</cupomFiscal>
<horaVenda xsi:nil="true"/>
<tipoVenda>1</tipoVenda>
<vendedorVip>FUlano de tal</vendedorVip>
<cpfCnpjAdquirente xsi:nil="true"/>
<item>
<numeroDoItem>9001</numeroDoItem>
<codigoDoProduto>2134</codigoDoProduto>
<qtde>1</qtde>
<valorUnitario>399.000</valorUnitario>
<ultimoCusto>216.150</ultimoCusto>
</item>
<item>
<numeroDoItem>9002</numeroDoItem>
<codigoDoProduto>32134</codigoDoProduto>
<qtde>1</qtde>
<valorUnitario>399.000</valorUnitario>
<ultimoCusto>216.150</ultimoCusto>
</item>
</cupomVenda>
<cupomVenda>
<codFilial>234567</codFilial>
<dtVenda>2013-01-01T00:00:00</dtVenda>
<numeroDePdv>0.000000000000000</numeroDePdv>
<cupomFiscal>23456</cupomFiscal>
<horaVenda xsi:nil="true"/>
<tipoVenda>4</tipoVenda>
<vendedorVip>FUlano de tal</vendedorVip>
<cpfCnpjAdquirente xsi:nil="true"/>
<item>
<numeroDoItem>9011</numeroDoItem>
<codigoDoProduto>3256</codigoDoProduto>
<qtde>4</qtde>
<valorUnitario>333.44</valorUnitario>
<ultimoCusto>333.55</ultimoCusto>
</item>
<item>
<numeroDoItem>9013</numeroDoItem>
<codigoDoProduto>33256</codigoDoProduto>
<qtde>4</qtde>
<valorUnitario>333.44</valorUnitario>
<ultimoCusto>333.55</ultimoCusto>
</item>
</cupomVenda>
</listaCupons>
';
INSERT INTO #DestinationCupomVendaParentTable (codFilialNaturalKey , tipoVenda)
SELECT T.parentEntity.value('(codFilial)[1]', 'INT') AS codFilial,
T.parentEntity.value('(tipoVenda)[1]', 'INT') AS tipoVenda
FROM @data.nodes('listaCupons/cupomVenda') AS T(parentEntity)
/* add a where not exists check on the natural key */
where not exists (
select null from #DestinationCupomVendaParentTable innerRealTable where innerRealTable.codFilialNaturalKey = T.parentEntity.value('(codFilial)[1]', 'INT'))
;
/* Optional. You could do a UPDATE here based on matching the #DestinationCupomVendaParentTablecodFilialNaturalKey = T.parentEntity.value('(codFilial)[1]', 'INT')
You could Combine INSERT and UPDATE using the MERGE function on 2008 or later.
*/
INSERT INTO #DestinationItemCupomVendaChildTable ( CupomVendaParentSurrogateIdentityKeyFK , numeroDoItemNaturalKey , codigoDoProduto)
SELECT par.CupomVendaParentSurrogateIdentityKey ,
T.childEntity.value('(numeroDoItem)[1]', 'INT') AS numeroDoItem,
T.childEntity.value('(codigoDoProduto)[1]', 'INT') AS codigoDoProduto
FROM @data.nodes('listaCupons/cupomVenda/item') AS T(childEntity)
/* The next join is the "trick". Join on the natural key (codFilial)....**BUT** insert the CupomVendaParentSurrogateIdentityKey into the table */
join #DestinationCupomVendaParentTable par on par.codFilialNaturalKey = T.childEntity.value('(../codFilial)[1]', 'INT')
where not exists (
select null from #DestinationItemCupomVendaChildTable innerRealTable where innerRealTable.CupomVendaParentSurrogateIdentityKeyFK = par.CupomVendaParentSurrogateIdentityKey AND innerRealTable.numeroDoItemNaturalKey = T.childEntity.value('(numeroDoItem)[1]', 'INT'))
;
print '/#DestinationCupomVendaParentTable/'
select * from #DestinationCupomVendaParentTable
print '/#DestinationItemCupomVendaChildTable/'
select * from #DestinationItemCupomVendaChildTable
select codFilialNaturalKey , tipoVenda , numeroDoItemNaturalKey , codigoDoProduto , par.CupomVendaParentSurrogateIdentityKey as ParentPK , child.CupomVendaParentSurrogateIdentityKeyFK as childFK from #DestinationCupomVendaParentTable par join #DestinationItemCupomVendaChildTable child
on par.CupomVendaParentSurrogateIdentityKey = child.CupomVendaParentSurrogateIdentityKeyFK
IF OBJECT_ID('tempdb..#DestinationCupomVendaParentTable') IS NOT NULL
begin
drop table #DestinationCupomVendaParentTable
end
IF OBJECT_ID('tempdb..#DestinationItemCupomVendaChildTable') IS NOT NULL
begin
drop table #DestinationItemCupomVendaChildTable
end
Voici une UDF pour convertir un DataSet DateTime à une valeur SqlServer:
if exists (select * from sysobjects where id = object_id('udfConvertXmlDateToTsqlDate') and xtype = 'FN')
drop function udfConvertXmlDateToTsqlDate
GO
CREATE FUNCTION dbo.udfConvertXmlDateToTsqlDate (@input_xml_date varchar(64))
/*
Original Need : When adding a value to a DataSet/datetime column,
the DataSet stores the date as an xml formatted date
TSQL does not like xml formatted dates
This procedure will transfer a xml formatted date,
into a datetime tsql datatype.
Sample Usage :
select dbo.udfConvertXmlDateToTsqlDate ('2002-06-20T00:00:00.0000000+05:30') as myConvertedDate
will yield:
myConvertedDate
------------------------------------------------------
2002-06-20 00:00:00.000
DateTime.MinValue Test
select dbo.udfConvertXmlDateToTsqlDate ('0001-01-01T00:00:00-05:00') as myConvertedDate
Notes :
The procedure strips out the time part of the datetime.
*/
RETURNS
datetime
AS
BEGIN
--This is a DotNet/Xml/DataSet and DateTime.MinValue work around
if LEFT(@input_xml_date,16) = '0001-01-01T00:00' -- :00-05:00'
BEGIN
return null
END
RETURN
--CONVERT(datetime , LEFT(@input_xml_date , (CHARINDEX('T', @input_xml_date))-1))
CONVERT(datetime , LEFT(CONVERT(nvarchar(4000), @input_xml_date, 126), 10))
-- SEE "Data Type Coercions" (SQL Server 2000 Books Online)
-- this has the code above as the translation mechanism
-- for converted an xml formatted datestamp into a TSQL datetime
END
GO
GRANT REFERENCES ON udfConvertXmlDateToTsqlDate TO public
GO
Dans quel genre de structure de la table vous allez stocker? – tucaz
Avez-vous regardé l'objet [SQLXMLBulkLoad] (http://msdn.microsoft.com/en-us/library/ms171993.aspx)? Il existe des instructions spécifiques pour l'utiliser avec .NET [ici] (http://msdn.microsoft.com/en-us/library/ms171878.aspx). – Pondlife
Table cupomVenda, champ idCupomVenda (incrément automatique) plus les mêmes champs en XML, dans l'ordre respectif de type: int, int, date, varchar (20), int, smallint, bit, varchar (80), char (14). Et aussi je vais stocker dans la table Item, avec IdItemCupomVenda (incrément automatique), plus les types de champs dans le même ordre que les champs dans xml: int, int, int, float, float. Plus idCupomVenda (int), pour faire la relation entre eux deux. Merci de votre aide! –