2014-01-31 24 views
0

我發現,每天基本更新(在網絡上)的XML文件,我想在這個文件中的數據創建一個數據庫表,並需要將其更新的選項,任何幫助嗎?如何從XML文件更新SQL數據庫表?

我使用微軟的Visual Web Developer 2010年,我該怎麼辦?

+1

這將是很好的,你要表現出[你嘗試過什麼(http://whathaveyoutried.com) 。 – Yuriy

+0

你正在使用哪個數據庫? – Avisho

+0

我沒有嘗試過任何東西,因爲我真的不知道如何啓動,這是xml文件:http://www.boi.org.il/currency.xml,我使用sql server databse(.mdf) – user1560934

回答

2

我會如下其存儲在一個表(與您所選擇的主鍵,我猜要麼替代標識列或貨幣代碼和最近更新複合鍵):

CREATE TABLE dbo.Currency 
( 
    LastUpdate DATE NOT NULL, 
    CurrencyCode CHAR(3) NOT NULL, 
    Name NVARCHAR(10) NOT NULL, 
    Unit INT NOT NULL, 
    Country NVARCHAR(50) NOT NULL, 
    Rate DECIMAL(10, 4) NOT NULL, 
    Change DECIMAL(10, 4) NOT NULL 
); 

然後您可以將文件保存爲一個存儲過程和查詢與XQuery的XML:

CREATE PROCEDURE dbo.SaveCurrencyXML @XML XML 
AS 

    INSERT dbo.Currency (LastUpdate, CurrencyCode, Name, Unit, Country, Rate, Change) 
    SELECT LastUpdate = @XML.value('CURRENCIES[1]/LAST_UPDATE[1]', 'DATE'), 
      CurrencyCode = Currency.value('CURRENCYCODE[1]', 'CHAR(3)'), 
      Name = Currency.value('NAME[1]', 'NVARCHAR(50)'), 
      Unit = Currency.value('UNIT[1]', 'INT'), 
      Country = Currency.value('COUNTRY[1]', 'NVARCHAR(50)'), 
      Rate = Currency.value('RATE[1]', 'DECIMAL(10, 4)'), 
      Change = Currency.value('CHANGE[1]', 'DECIMAL(10, 4)') 
    FROM @XML.nodes('CURRENCIES/CURRENCY') c (Currency); 
    GO 

但如果你使用組合鍵,你將需要使用MERGE:

CREATE PROCEDURE dbo.SaveCurrencyXMLMERGE @XML XML 
AS 
    WITH C AS 
    ( SELECT LastUpdate = @XML.value('CURRENCIES[1]/LAST_UPDATE[1]', 'DATE'), 
       CurrencyCode = Currency.value('CURRENCYCODE[1]', 'CHAR(3)'), 
       Name = Currency.value('NAME[1]', 'NVARCHAR(50)'), 
       Unit = Currency.value('UNIT[1]', 'INT'), 
       Country = Currency.value('COUNTRY[1]', 'NVARCHAR(50)'), 
       Rate = Currency.value('RATE[1]', 'DECIMAL(10, 4)'), 
       Change = Currency.value('CHANGE[1]', 'DECIMAL(10, 4)') 
     FROM @XML.nodes('CURRENCIES/CURRENCY') c (Currency) 
    ) 
    MERGE dbo.Currency cu 
    USING C 
     ON C.LastUpdate = cu.LastUpdate 
     AND C.CurrencyCode = cu.CurrencyCode 
    WHEN MATCHED AND 
       C.Name != cu.Name 
      OR C.Unit != cu.Unit 
      OR C.Country != cu.Country 
      OR C.Rate != cu.Rate 
      OR C.Change != cu.Change 
     THEN UPDATE 
     SET Name = C.Name, 
      Unit = C.Unit, 
      Country = C.Country, 
      Rate = C.Rate, 
      Change = C.Change 
    WHEN NOT MATCHED THEN 
     INSERT (LastUpdate, CurrencyCode, Name, Unit, Country, Rate, Change) 
     VALUES (C.LastUpdate, C.CurrencyCode, C.Name, C.Unit, C.Country, C.Rate, C.Change); 

然後你可以簡單地調用你的程序,以節省您的數據:當你說你用插入

DECLARE @X XML = '<CURRENCIES> 
        <LAST_UPDATE>2014-01-30</LAST_UPDATE> 
        <CURRENCY><NAME>Dollar</NAME><UNIT>1</UNIT><CURRENCYCODE>USD</CURRENCYCODE><COUNTRY>USA</COUNTRY><RATE>3.492</RATE><CHANGE>0.057</CHANGE></CURRENCY> 
        <CURRENCY><NAME>Pound</NAME><UNIT>1</UNIT><CURRENCYCODE>GBP</CURRENCYCODE><COUNTRY>Great Britain</COUNTRY><RATE>5.7575</RATE><CHANGE>-0.312</CHANGE></CURRENCY> 
        <CURRENCY><NAME>Yen</NAME><UNIT>100</UNIT><CURRENCYCODE>JPY</CURRENCYCODE><COUNTRY>Japan</COUNTRY><RATE>3.4087</RATE><CHANGE>0.383</CHANGE></CURRENCY><CURRENCY><NAME>Euro</NAME><UNIT>1</UNIT><CURRENCYCODE>EUR</CURRENCYCODE><COUNTRY>EMU</COUNTRY><RATE>4.7492</RATE><CHANGE>-0.204</CHANGE></CURRENCY> 
        <CURRENCY><NAME>Dollar</NAME><UNIT>1</UNIT><CURRENCYCODE>AUD</CURRENCYCODE><COUNTRY>Australia</COUNTRY><RATE>3.0620</RATE><CHANGE>0.219</CHANGE></CURRENCY> 
        <CURRENCY><NAME>Dollar</NAME><UNIT>1</UNIT><CURRENCYCODE>CAD</CURRENCYCODE><COUNTRY>Canada</COUNTRY><RATE>3.1225</RATE><CHANGE>-0.24</CHANGE></CURRENCY> 
        <CURRENCY><NAME>krone</NAME><UNIT>1</UNIT><CURRENCYCODE>DKK</CURRENCYCODE><COUNTRY>Denmark</COUNTRY><RATE>0.6365</RATE><CHANGE>-0.188</CHANGE></CURRENCY> 
        <CURRENCY><NAME>Krone</NAME><UNIT>1</UNIT><CURRENCYCODE>NOK</CURRENCYCODE><COUNTRY>Norway</COUNTRY><RATE>0.5602</RATE><CHANGE>-0.568</CHANGE></CURRENCY> 
        <CURRENCY><NAME>Rand</NAME><UNIT>1</UNIT><CURRENCYCODE>ZAR</CURRENCYCODE><COUNTRY>South Africa</COUNTRY><RATE>0.3099</RATE><CHANGE>-1.054</CHANGE></CURRENCY> 
        <CURRENCY><NAME>Krona</NAME><UNIT>1</UNIT><CURRENCYCODE>SEK</CURRENCYCODE><COUNTRY>Sweden</COUNTRY><RATE>0.5378</RATE><CHANGE>-0.407</CHANGE></CURRENCY> 
        <CURRENCY><NAME>Franc</NAME><UNIT>1</UNIT><CURRENCYCODE>CHF</CURRENCYCODE><COUNTRY>Switzerland</COUNTRY><RATE>3.8827</RATE><CHANGE>0.072</CHANGE></CURRENCY> 
        <CURRENCY><NAME>Dinar</NAME><UNIT>1</UNIT><CURRENCYCODE>JOD</CURRENCYCODE><COUNTRY>Jordan</COUNTRY><RATE>4.9370</RATE><CHANGE>0.032</CHANGE></CURRENCY> 
        <CURRENCY><NAME>Pound</NAME><UNIT>10</UNIT><CURRENCYCODE>LBP</CURRENCYCODE><COUNTRY>Lebanon</COUNTRY><RATE>0.0232</RATE><CHANGE>0</CHANGE></CURRENCY> 
        <CURRENCY><NAME>Pound</NAME><UNIT>1</UNIT><CURRENCYCODE>EGP</CURRENCYCODE><COUNTRY>Egypt</COUNTRY><RATE>0.5016</RATE><CHANGE>0.06</CHANGE></CURRENCY> 
       </CURRENCIES>'; 

EXECUTE dbo.SaveCurrencyXML @X; 

Example on SQL Fiddle


附錄

我認爲:

Insert into History values('{0}','{1}','{2}','{3}','{4}')", date, id, "Deposit", amount, curr 

你實際使用的是String.Format,即:

var sql = String.Format("Insert into History values('{0}','{1}','{2}','{3}','{4}')", date, id, "Deposit", amount, curr); 

如果是這樣請立即停止。這是非常糟糕的做法,它不僅使你vunerable到SQL injection,它每次也迫使查詢的重新編譯,因爲它是無法利用的cached query plans。 另一個缺點是,它不是強類型,在您的查詢中,假設dateDateTime類型,您將自動調用ToString()方法,該方法將返回一個依賴於調用它的線程的區域性信息的字符串,不能保證輸出字符串將在數據庫識別爲日期時間的格式,所以如果你的目標列是一個日期,你會得到一個轉換錯誤。

相反,你應該使用參數化查詢,但首先,雖然我懷疑你也可能已縮短您例如目的的查詢,但它始終是一個好主意,explicitly state the column list插入時,讓你的最終查詢會變成:

var sql = "INSERT History (Date, Id, Deposit, Amount, Curr) VALUES (@Date, @Id, @Deposit, @Amount, @Curr);"; 

然後,您需要爲您的參數添加到您的SqlCommand,如

var date = DateTime.Now; 
command.Parameters.AddWithValue("@Date", date); 

這意味着,當發送到DB查詢將把@Date作爲一個DateTime(因爲傳遞的值是一個日期時間),這意味着你的查詢更加類型安全。

因此,對於你的榜樣,調用存儲過程上面,你會使用類似:

//using System.Xml; 
//using System.Data.SqlClient; 
//using System.Data.SqlTypes; 

XmlDocument xmldoc = new XmlDocument(); 
xmldoc.Load(@"YourXMLFile.xml"); 
using (var connection = new SqlConnection("ConnectionString")) 
using (var command = new SqlCommand("dbo.SaveCurrencyXML", connection)) 
{ 
    var xml = new SqlXml(new XmlTextReader(xmldoc.InnerXml, XmlNodeType.Document, null)); 
    var param = new SqlParameter("@XML", SqlDbType.Xml).Value = xml; 
    command.Parameters.Add(param); 
    command.ExecuteNonQuery(); 
} 
+0

非常感謝你!我會盡快嘗試 – user1560934

+0

首先,我想再次感謝您的幫助,但我無法理解這一點,在我的課堂上,我們使用的是C#中的Microsoft Web開發人員,當我們與查詢,例如「插入到歷史記錄值('{0}','{1}','{2}','{3}','{4}')',日期,編號, ,curr。那麼我應該在哪裏寫你給我的東西? – user1560934