我发现一个XML文件在每日基础(在网络上)上更新,我想从这个文件中的数据创建一个数据库表,并且可以选择更新它,任何帮助?
我正在使用Microsoft Visual Web developer 2010,我该怎么办?
答案 0 :(得分: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
查询XMLCREATE 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;
<强>附录
我假设当你说你插入时:
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);
如果是这样请立即停止。这是非常糟糕的做法,它不仅让你对SQL injection有所帮助,而且每次都会强制重新编译查询,因为它无法使用cached query plans。
另一个缺点是它没有强类型,在您的查询中,假设date
属于DateTime
类型,您自动调用此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);
这意味着当发送到数据库时,查询会将@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();
}