2010-08-03 68 views
1

我有一個XML文件,我需要填充多個SQL表,我想知道什麼是最好的方式來做到這一點。我在想數據集,或xslt,但我真的不知道。這是我生成的XML(的一部分)有XML文件需要它populatemultiple SQL表

<?xml version="1.0" encoding="utf-8" standalone="yes" ?> 
- <!-- Created: 8/3/2010 12:09:15 PM 
    --> 
- <Trip> 
- <TripDetails> 
    <DepartureDate /> 
    <ReturnDate /> 
    <TripTypeA>3</TripTypeA> 
    <TripTypeB>1</TripTypeB> 
    <PurposeOfTrip>vacation</PurposeOfTrip> 
    <Region>5</Region> 
- <Countries> 
    <Country>105</Country> 
    <Country>135</Country> 
    </Countries> 
- <Cities> 
    <City>Cancun</City> 
    <City>Tokyo</City> 
    <City>Mayo</City> 
    </Cities> 
    <OverallRating>4</OverallRating> 
    <Suppliers>53</Suppliers> 
    <SuppliersComments>Good flight</SuppliersComments> 
- <Transport> 
    <TransportType>1</TransportType> 
    <TransportType>3</TransportType> 
    </Transport> 
    <TransportComment>Transportation was fast</TransportComment> 

我有我需要填充。幾個不同的表(保持它短爲例)

TripDetails (TripID, TripTypeA, TripTypeB, SupplierID, overallRating) 
TripCountries (TripCountryID, TripID, CountryCode) 

我有一大堆的多個表(市,運輸),但如果我能想出如何更新TripDetails(主表)和TripCountries(這是一個彙集TripDetails和國家的表格),我想我會很好,謝謝!

+0

使用SQL服務器 – Spooks 2010-08-03 16:27:39

+0

我認爲應該用''關閉? – 2010-08-03 16:28:43

+0

right right,sorry,我剛剛複製了我的xml代碼片段 – Spooks 2010-08-03 16:33:09

回答

1

假設您使用的是SQL Server,您應該將XML解析爲DataTable,並使用SqlBulkCopy對象以超快的速度將它們投射到數據庫中。有很多資源可以幫助您瞭解SqlBulkCopy。下面是另一個StackOverflow問題的最新討論,以幫助您入門:Sql Server 2008 Tuning with large transactions (700k+ rows/transaction)

如果XML文件非常大,那麼您應該小心使用哪種解析器。 XDocument和XmlDocument將整個事物加載到內存中。如果文件足夠小,例如10MB以下,那麼使用這些解析器應該沒問題。


編輯:

這裏是你如何能得到XML轉換的DataTable快速實物模型。這是在VB中,因爲VB使XML更容易一些。

Option Strict On : Option Explicit On : Option Infer On : Option Compare Binary 

Imports System.Data 
Imports System.Linq 
Imports System.Xml.Linq 

Module Module1 

    Sub Main() 
     Dim xml = 
     <Trip> 
      <TripDetails id="1"> 
       <DepartureDate/> 
       <ReturnDate/> 
       <TripTypeA>3</TripTypeA> 
       <TripTypeB>1</TripTypeB> 
       <PurposeOfTrip>vacation</PurposeOfTrip> 
       <Region>5</Region> 
       <Countries> 
        <Country>105</Country> 
        <Country>135</Country> 
       </Countries> 
       <Cities> 
        <City>Cancun</City> 
        <City>Tokyo</City> 
        <City>Mayo</City> 
       </Cities> 
       <OverallRating>4</OverallRating> 
       <Suppliers>53</Suppliers> 
       <SuppliersComments>Good flight</SuppliersComments> 
       <Transport> 
        <TransportType>1</TransportType> 
        <TransportType>3</TransportType> 
       </Transport> 
       <TransportComment>Transportation was fast</TransportComment> 
      </TripDetails> 
     </Trip> 

     Dim dtTripDetails As New DataTable() 
     With dtTripDetails.Columns 
      .Add("TripID", GetType(Integer)) 
      .Add("TripTypeA", GetType(Integer)) 
      .Add("DepartureDate", GetType(DateTime)) 
      .Add("TransportComment", GetType(String)) 
     End With 

     Dim dtTripDetailXrefCountries As New DataTable() 
     With dtTripDetailXrefCountries.Columns 
      .Add("TripID", GetType(Integer)) 
      .Add("CountryID", GetType(Integer)) 
     End With 

     Dim xdetails = From td In xml.Descendants("TripDetails") Select td 
     For Each xdetailRecord As XElement In xdetails 
      Dim tripID As Integer = CInt(xdetailRecord.Attribute("id").Value) 
      Dim tripTypeA As Integer = CInt(xdetailRecord.Element("TripTypeA").Value) 
      Dim strDepDate As String = xdetailRecord.Element("DepartureDate").Value 
      Dim depDate As Object = If(String.IsNullOrEmpty(strDepDate), CType(DBNull.Value, Object), CType(DateTime.Parse(strDepDate), Object)) 
      Dim transportComment As String = xdetailRecord.Element("TransportComment").Value 
      dtTripDetails.Rows.Add(tripID, tripTypeA, depDate, transportComment) 

      Dim xcountries = From c In xdetailRecord.Element("Countries").Elements("Country") Select c 
      For Each xcountryRecord As XElement In xcountries 
       Dim countryID As Integer = CInt(xcountryRecord.Value) 
       dtTripDetailXrefCountries.Rows.Add(tripID, countryID) 
      Next 
     Next 

     Console.WriteLine("Done") 
     Console.ReadKey(True) 

    End Sub 

End Module 

順便說一句 - 當做這樣的ETL時,最好先將數據抽取到登臺表中,而不是直接輸入到生產表中。這樣,您就可以驗證數據類型,並確保參照完整性並處理密鑰管理,並使所有內容完美無缺地鎖定或污染您的生產表。

+0

感謝您的快速回復,我會研究一下。我創建的文件小於2mb(否則應該使用什麼?只是好奇),我正在使用SQL Server 2008.因此,對於我的SQL Server中的每個表,我應該創建一個新的DataTable,然後插入SqlBulkCopy? – Spooks 2010-08-03 16:28:42

+0

對於如何只向數據表/數據集添加特定部分仍然有點困惑 – Spooks 2010-08-03 16:33:32

+0

1 DataTable映射到1個SQL表,所以是的 - 你需要一對一的映射。您提到對不同部分感到困惑 - 我假設您問的是如何獲取XML文件中的不同數據。如果您使用舊的XmlDocument,則可能需要XPath。但是,如果您可以使用3.5框架,我推薦使用XDocument,然後您可以使用Linq查詢您的XML文件並獲取所需的數據元素。因此,您將開始循環瀏覽TripDetails節點並填充您的TripDetails DataTable,然後選擇子節點並填充這些表。 – mattmc3 2010-08-03 16:41:03

0

您可以很容易地使用SQL Server 2005的XQuery功能,例如,有一個存儲過程,關於這些XML字符串作爲輸入的接受:

CREATE PROCEDURE dbo.StoreTripDetails(@XmlContent XML) 
AS BEGIN 
    DECLARE @NewTripID INT 

    INSERT INTO dbo.TripDetails(TripTypeA, TripTypeB, SupplierID, overallRating) 
     SELECT 
     Trip.Details.value('(TripTypeA)[1]', 'int') 'TripTypeA', 
     Trip.Details.value('(TripTypeB)[1]', 'int') 'TripTypeB', 
     Trip.Details.value('(Suppliers)[1]', 'int') 'SupplierID', 
     Trip.Details.value('(OverallRating)[1]', 'int') 'OverallRating' 
     FROM 
     @XmlContent.nodes('/Trip/TripDetails') AS Trip(Details) 

    SELECT @NewTripID = SCOPE_IDENTITY() 

    INSERT INTO dbo.TripCountries(TripID, CountryCode) 
     SELECT 
     @NewTripID, Trip.Countries.value('(.)[1]', 'int') 
     FROM 
     @XmlContent.nodes('/Trip/TripDetails/Countries/Country') AS Trip(Countries) 
END 

,然後你可以很容易地調用從C#代碼這個存儲過程並傳遞一個代表XML之旅一大塊。

0

您需要指定您正在使用的數據庫引擎。既然你已經指定了Linq標籤,我假設你正在使用Microsoft SQL服務器。

您可以輕鬆地將文檔作爲字符串傳遞給存儲過程。在此存儲過程中,您可以定義一些臨時表模式,並使用sp_xml_preparedocument,OPENXML(和相關函數)使用XML文檔中的數據填充這些臨時表。現在,您可以使用標準SQL從臨時表中使用任何投影,連接或其他需要的轉換插入到永久表中。內存在大多數情況下也不再是問題,因爲它全部在MSSQL Server內完成。

更多信息: http://msdn.microsoft.com/en-us/library/aa260385(SQL.80).aspx http://msdn.microsoft.com/en-us/library/aa276847(SQL.80).aspx

例(未經測試):

declare @docHandle int 
declare @xmlContent varchar(500) 
set @doc ='<root><items><item value="1"/><item value="2"/></item></root>' 

exec sp_xml_preparedocument @docHandle OUTPUT, @xmlContent 

insert into myTable ([ItemValue]) 
select value from OPENXML(@docHandle, '/root/items/item') 

exec sp_xml_removedocument @docHandle 

注意,這些是SQL 2000條的約定。在SQL 2005中,存在比這些存儲過程前輩更具可讀性的等效T-SQL約定。不過,我相信這些約定在SQL 2005和SQL 2008中仍然可用。