博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
使用XML向SQL Server 2005批量写入数据——一次有关XML时间格式的折腾经历
阅读量:6111 次
发布时间:2019-06-21

本文共 3923 字,大约阅读时间需要 13 分钟。

 
原文:

常常遇到需要向SQL Server插入批量数据,然后在存储过程中对这些数据进行进一步处理的情况。存储过程并没有数组、列表之类的参数类型,使用XML类型可妥善解决这个问题。

不过,SQL Server2005对标准xml的支持不足,很多地方需要特别处理。举一个例子说明一下。

这个场景是往存储过程里传递一个xml序列化了的List<Model>。

1.Model的代码如下,这是一个实体类

public class Model{    ///     /// UIN ///  [XmlElement("UIN")] public long UIN { get; set; } ///  /// 昵称 ///  [XmlElement("Name")] public string Name { get; set; } ///  /// 头像 ///  [XmlElement("Img")] public string Img { get; set; } ///  /// 访问时间 ///  [XmlElement("VisitTime")] public DateTime VisitTime { get; set; } }

然后我们需要将这个List<Model>序列化成一个xml的字符串。但是SQL Server对xml的命名空间识别是有问题的,.net默认的序列化会出现xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd=

有网友给出了一个完美序列化Sql Server2005支持的xml的类(参考):

 

public static class DbXml{    private static readonly XmlSerializerNamespaces Namespaces = new XmlSerializerNamespaces(); static DbXml() { //去掉 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" Namespaces.Add(string.Empty, string.Empty); } ///  /// 把一个对象序列化成一个Xml字符串 ///  /// 
/// ///
public static string SerializeXml
(T obj) { XmlSerializer serializer = new XmlSerializer(typeof(T)); using (MemoryStream stream = new MemoryStream()) { serializer.Serialize(stream, obj, Namespaces); return Encoding.UTF8.GetString(stream.ToArray()); } } public static T DeserializeXml
(string obj) { XmlSerializer serializer = new XmlSerializer(typeof(T)); using (StringReader reader = new StringReader(obj)) { return (T)serializer.Deserialize(reader); } } }

使用的时候只需要:string xml = DbXml.SerializeXml<List<QQVisitorXml>>(list) 即可获取序列化后的xml字符串:

0
name0
img0
2009-07-17T00:00:00-05:00
1
name1
img1
2009-07-17T00:00:00-05:00
2
name2
img2
2009-07-17T00:00:00-05:00

2.存储过程里,读取xml到一个临时表#temp里:

select c.value('(UIN)[1]','varchar(30)') as uin, c.value('(Name)[1]','varchar(50)') as Name, c.value('(Img)[1]','varchar(200)') as Img, c.value('(VisitTime)[1]','datetime') as VisitTime into #temp from @strxml.nodes('//Model') T(c) --@strxml是存储过程的xml参数

然后就可以对#temp按照普通表进行进一步处理。

我们试着执行这个存储过程。嗯?出错了?!

3.原来,XML的时间标准格式是”年-月-日T时:分:秒-时区” SQL Server2005不支持时区,所以它也不能支持xml的时间格式(倒是支持年-月-日T时:分:秒)。这个问题在SQL server 2008中得到改进,完整支持了xml的时间格式。但是我们数据库是2005,没办法,得想个办法解决。解决办法是把时间字转成字符串,然后截取 年-月-日T时:分:秒,最后再加上东八区的时区数,这样sql修正为:

select c.value('(UIN)[1]','varchar(30)') as uin, c.value('(Name)[1]','varchar(50)') as Name, c.value('(Img)[1]','varchar(200)') as Img, dateadd(hour,8,convert(datetime,left(t.c.value('(VisitTime)[1]','varchar(30)'), 19),127)) as VisitTime into #temp from @strxml.nodes('//Model') T(c) --@strxml是存储过程的xml参数

本地测试,成功!

4.放到服务器上测试,执行倒是成功了,可以一查看数据,又出问题了!服务器上插入数据表的时间,和我本地测试数据库的时间,相差8个小时!本地开发环境是windows8,服务器是windows server 2008。开发环境和服务器环境有差异,导致本地获取xml带时区,服务器不带时区。

过于依赖环境,就太危险了!果断放弃时间格式,修改Model中时间为字符串:

public class Model{    ///     /// UIN ///  [XmlElement("UIN")] public long UIN { get; set; } ///  /// 昵称 ///  [XmlElement("Name")] public string Name { get; set; } ///  /// 头像 ///  [XmlElement("Img")] public string Img { get; set; } ///  /// 访问时间 ///  [XmlIgnore] //xml序列化时跳过 public DateTime VisitTime { get; set; } [XmlElement("VisitTime")] public string XVisitTime { get { return this.VisitTime.ToString("yyyy-MM-dd HH:mm:ss"); } set { this.VisitTime = DateTime.Parse(value); } } }

在存储过程中把这个时间字符串转换成时间:

select c.value('(UIN)[1]','varchar(30)') as uin, c.value('(Name)[1]','varchar(50)') as Name, c.value('(Img)[1]','varchar(200)') as Img, convert(datetime,c.value('(VisitTime)[1]','varchar(30)')) as VisitTime into #temp from @strxml.nodes('//Model') T(c)

Ok。所有问题都解决了,畅快。

转载地址:http://racka.baihongyu.com/

你可能感兴趣的文章
Oracle中drop user和drop user cascade的区别
查看>>
【Linux】linux经常使用基本命令
查看>>
Java 内存区域和GC机制
查看>>
更新代码和工具,组织起来,提供所有博文(C++,2014.09)
查看>>
HTML模块化:使用HTML5 Boilerplate模板
查看>>
登记申请汇总
查看>>
Google最新截屏案例详解
查看>>
2015第31周一
查看>>
2015第31周日
查看>>
在使用EF开发时候,遇到 using 语句中使用的类型必须可隐式转换为“System.IDisposable“ 这个问题。...
查看>>
PHP使用DES进行加密和解密
查看>>
Oracle 如何提交手册Cluster Table事务
查看>>
BeagleBone Black第八课板:建立Eclipse编程环境
查看>>
在服务器上用Fiddler抓取HTTPS流量
查看>>
文件类似的推理 -- 超级本征值(super feature)
查看>>
【XCode7+iOS9】http网路连接请求、MKPinAnnotationView自定义图片和BitCode相关错误--备用...
查看>>
各大公司容器云的技术栈对比
查看>>
记一次eclipse无法启动的排查过程
查看>>
【转】jmeter 进行java request测试
查看>>
读书笔记--MapReduce 适用场景 及 常见应用
查看>>