使用XML向SQL Server 2005批量写入数据——一次有关XML时间格式的折腾经历

使用XML向SQL Server 2005批量写入数据——一次有关XML时间格式的折腾经历

原文:使用XML向SQL Server 2005批量写入数据——一次有关XML时间格式的折腾经历

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

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

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

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

public class Model
{
    /// <summary>
    /// UIN
    /// </summary>
    [XmlElement("UIN")]
    public long UIN { get; set; }
    /// <summary>
    /// 昵称
    /// </summary>
    [XmlElement("Name")]
    public string Name { get; set; }
    /// <summary>
    /// 头像
    /// </summary>
    [XmlElement("Img")]
    public string Img { get; set; }
    /// <summary>
    /// 访问时间
    /// </summary>
    [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=http://www.w3.org/2001/XMLSchema

有网友给出了一个完美序列化Sql Server2005支持的xml的类(参考http://www.cnblogs.com/prime/archive/2012/10/11/SQLXML.html):

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);
    }
    /// <summary>
    /// 把一个对象序列化成一个Xml字符串
    /// </summary>
    /// <typeparam name="T"></typeparam>
    /// <param name="obj"></param>
    /// <returns></returns>
    public static string SerializeXml<T>(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<T>(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字符串:

<?xml version="1.0"?>
<ArrayOfModel>
  <Model>
    <UIN>0</UIN>
    <Name>name0</Name>
    <Img>img0</Img>
    <VisitTime>2009-07-17T00:00:00-05:00</VisitTime>
  </Model>
  <Model>
    <UIN>1</UIN>
    <Name>name1</Name>
    <Img>img1</Img>
    <VisitTime>2009-07-17T00:00:00-05:00</VisitTime>
  </Model>
  <Model>
    <UIN>2</UIN>
    <Name>name2</Name>
    <Img>img2</Img>
    <VisitTime>2009-07-17T00:00:00-05:00</VisitTime>
  </Model>
</ArrayOfModel>

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
{
    /// <summary>
    /// UIN
    /// </summary>
    [XmlElement("UIN")]
    public long UIN { get; set; }
    /// <summary>
    /// 昵称
    /// </summary>
    [XmlElement("Name")]
    public string Name { get; set; }
    /// <summary>
    /// 头像
    /// </summary>
    [XmlElement("Img")]
    public string Img { get; set; }
    /// <summary>
    /// 访问时间
    /// </summary>
    [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。所有问题都解决了,畅快。

时间: 2024-10-11 23:06:39

使用XML向SQL Server 2005批量写入数据——一次有关XML时间格式的折腾经历的相关文章

使用C#实现sql server 2005 和Oracle 数据同步

1.背景: 公司的一个项目进行服务扩展,添加了短信服务平台,实现平台按照预定义的规则给用户主动发送短信和用户点播,两种方式.短信平台需能够接入三网(移动.联通.电信).目前只接入了移动MAS机.用户点播时发送的短信通过MAS机,发送的内容最后保存在sql serer 2005 数据库的表T 中,然后需要根据用户发送的点播代码给用户返回对应的信息. 用户的信息都在业务系统中,业务系统是Oracle 的数据库.两者都处于同一个局域网之内.由于短信平台是一个产品我们无法进行操作,和项目经理商议后决定将

(转)SQL Server 2005的XML数据修改语言(XML DML) (转自MSDN)

SQL Server 2005的XML数据修改语言(XML DML) 发布日期: 2006-08-14 | 更新日期: 2006-08-14 作者:张洪举 Microsoft MVP 应用于:SQL Server 2005,XML 注:本文章中的内容需要相关的XML和XQuery知识 本页内容 1.insert 2.delete 3.replace 作为对XQuery语言的扩展,XML DML为XML数据操作提供了更大的灵活性,而不再仅仅是对XML数据进行一些查询操作.通过XML DML,用户可

22. SQL -- SQL Server 2005 和SQL Server 2008新特性

SQL SERVER 2005 与SQL SERVER 2008 新特性   SQLSERVER 2005 新特性 Enhanced Data Types:存储最大8K-2G Partitioned Table(分区表):数据拆分管理 背景:一个公司,有目前现存数据以及历史数据,各在一台SER 上,服务器访问方式: SQL 2000 TABLE 1:在一张table 中,对数据进行分区 Enhanced Indexing Features SER 1 SER 2 现存数据 TABLE 1 TAB

SQL SERVER 2005如何建立自动备份的维护计划

SQL Server 2005中可以使用维护计划来为数据库自动备份,减少数据库管理员的工作负担.其使用方法如下: (1)启动[sql server Management Studio],在[对象资源管理器]窗口里选择[管理]——[维护计划]选项. 2)右击[维护计划],在弹出的快捷菜单里选择[维护计划向导]选项 ,弹出如图所示的[维护计划向导]对话框,单击[下一步]按钮 3)弹出如图所示[选择目标服务器]对话框,在[名称]文本框里可以输入维护计划的名称:在[说明]文本框里可以输入维护计划的说明文

[转]Under the covers: IAM chains and allocation units in SQL Server 2005

(I'm sitting here in Seattle airport at 7am on Sunday waiting to catch the same flight to Boston that I caught two weeks ago. Instead of TechEd, this time I'm going to a training course at MIT. I'd enjoy the air travel a lot more with a bigger gap in

SQL Server 2005 镜像构建手册

转载:http://www.cnblogs.com/killkill/archive/2008/05/23/1205792.html 一. 镜像简介 1. 简介 数据库镜像是将数据库事务处理从一个SQL Server数据库移动到不同SQL Server环境中的另一个SQL Server数据库中.镜像不能直接访问;它只用在错误恢复的情况下才可以被访问. 要进行数据库镜像所需的最小需求包括了两个不同的SQL Server运行环境.主服务器被称为"主机",第二个服务器被称作"备机&

回首经典的SQL Server 2005

原创文章转载请注明出处:@协思, http://amwicfai.cnblogs.com SQL Server是我使用时间最长的数据库,算起来已经有10年了.上世纪90年代,微软在软件开发的所有领域高歌猛进,形成了操作系统.办公软件.企业开发.游戏制作.浏览器各领域的全线垄断.那曾经是微软发展的黄金时期,至到今天,它仍然在享受着当年的红利. 在SQL Server 2000那个年代,由其功能强大,使用方便,“国人免费”等特点迅速流行起来,成为企业开发的不二选择.早期的用友.管家婆的ERP也使用此

在 SQL Server 2005 中配置数据库邮件

一.            SQL Server发邮件原理和组件介绍: 数据库邮件有4个组件:配置文件.邮件处理组件.可执行文件以及"日志记录和审核组件". l  配置组件包括: 1)数据库邮件帐户包含诸如SMTP服务器名.身份验证类型和电子邮件地址等. 2)数据库邮件配置文件是数据库邮件帐户的集合. l  邮件处理组件 要的数据库邮件组件就是刚才所说的数据库邮件主机数据库,默认是msdb. l  数据库邮件可执行文件 数据库邮件使用一个外部可执行文件来处理邮件,降低了对SQL Ser

SQL Server 2005中的CHECKSUM功能

原文:SQL Server 2005中的CHECKSUM功能 转自此处 页面 checksum 是SQL2005的新功能,提供了一种比残缺页检测强大的机制检测IO方面的损坏.以下是详细描述: 页面 CHECKSUM: 在数据库页面从被写入磁盘到被SQL Server读取的这段时间内,有可能由于外界原因发生损坏.比如I/O设备的损坏,驱动的损坏或者由于电源不稳没有写完整.Checksum机制使SQL Server可以检测到这些损坏.需要注意的是,Checksum机制只能使我们确定是不是I/O子系统