使用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。所有问题都解决了,畅快。
使用XML向SQL Server 2005批量写入数据——一次有关XML时间格式的折腾经历的更多相关文章
- 使用XML向SQL Server 2005批量写入数据——一次有关XML时间格式的折腾经历
原文:使用XML向SQL Server 2005批量写入数据——一次有关XML时间格式的折腾经历 常常遇到需要向SQL Server插入批量数据,然后在存储过程中对这些数据进行进一步处理的情况.存储过 ...
- SQL Server 2008 批量插入数据时报错
前几天在SQL Server 2008同步产品数据时,总是提示二进制文本被截断的错误,但是经过检查发现数据都符合格式要求. 百思不得其解,单独插入一条条数据则可以插入,但是批量导入则报错. 批量导入代 ...
- SQL Server中批量替换数据
SQL Server数据库中批量替换数据的方法 SQL Server数据库操作中,我们可能会根据某写需要去批量替换数据,那么如何批量修改替换数据呢?本文我们就介绍这一部分内容,接下来就让我们一起来了解 ...
- SQL Server TVPs 批量插入数据
在SQL Server 中插入一条数据使用Insert语句,但是如果想要批量插入一堆数据的话,循环使用Insert不仅效率低,而且会导致SQL一系统性能问题.下面介绍SQL Server支持的两种批量 ...
- 从TXT文本文档向Sql Server中批量导入数据
下面我们通过以下的简单的SQL语句即可实现数据的批量导入,代码如下: Bulk insert id From 'G:\文档\test.txt' With ( fieldterminator=',', ...
- 在Sql Server 2005中将主子表关系的XML文档转换成主子表“Join”形式的表
本文转载:http://www.cnblogs.com/Ricky81317/archive/2010/01/06/1640434.html 最近这段时间在Sql Server 2005下做了很多根据 ...
- SQL Server 2005 盛宴系列 经典教程
SQL Server 2005 盛宴系列 经典教程 [复制链接] 发表于 2007-3-27 14:08 | 来自 51CTO网页 [只看他] 楼主 TECHNET SQL serve ...
- 转载--SQL Server 2005的XQuery介绍
原文地址: http://bbs.51cto.com/thread-458009-1-1.html 引用: 摘要 本文介绍了SQL Server 2005能够支持的XQuery的各方面特性如FLW ...
- SQL Server 2005的XML数据修改语言(XML DML)
转:http://www.microsoft.com/china/msdn/library/data/sqlserver/XMLDML.mspx?mfr=true 作为对XQuery语言的扩展,XML ...
随机推荐
- python基础===多进程
进程线程的区别在进程,线程,协程的区别 linux或者unix有fork()函数,但是不支持win系统. multiprocessing multiprocessing模块是跨平台版本的多进程模块.支 ...
- zip函数的应用
#!/usr/bin/env python # encoding: utf-8 from itertools import zip_longest # ➍ # zip并行从输入的各个可迭代对象中获取元 ...
- HTML5API(2)
四.文件API 1.概述 H5允许JS有条件的读取客户端文件 允许读取的文件:1.待上传的文件2.拖进浏览器的文件 多文件上传设置属性multiple 过滤上传文件类型 设置accept属性 acce ...
- mybatis开启字段自动映射为java驼峰命名规则
<settings> <setting name="mapUnderscoreToCamelCase" value="true"/> & ...
- 算法入门系列2:k近邻算法
用官方的话来说,所谓K近邻算法(k-Nearest Neighbor,KNN),即是给定一个训练数据集,对新的输入实例,在训练数据集中找到与该实例最邻近的K个实例(也就是上面所说的K个邻居), 这K个 ...
- Tomcat手动指定jdk路径
Windows系统: 修改bin下的setclasspath.bat,在开头处添加: rem set specific jdkset JAVA_HOME=%CATALINA_HOME%\jdk1.8. ...
- 一台服务器支持多少TCP并发链接
误区一 1.文件句柄---文件描述符 每开一个链接,都要消耗一个文件套接字,当文件描述符用完,系统会返回can't open so many files 这时你需要明白操作系统对可以打开的最大文件数 ...
- 《java并发编程实战》读书笔记1--线程安全性,内置锁,重入,状态
什么是线程安全? 当多个线程访问某个类时,不管这些的线程的执行顺序如何,并且在主调代码中不需要任何额外的同步或协同,这个类都能表现出正确的行为,那么就称这个类是线程安全的. 哈哈书上的解释,还是翻译过 ...
- Git----创建远程分支,并将文件上传到创建的远程分支上
1.首先创建一个远程仓库 2.将远程仓库克隆到本地 (1)本地新建文件夹,命令行进入文件夹,执行clone操作 (2) git clone git@github.com:Lucky-Syw/lucky ...
- 亲测能用的mysqli类,挺好用的
<?php header('content-type:text/html;charset=utf-8'); /* 掌握满足单例模式的必要条件 (1)私有的构造方法-为了防止在类外使用new关键字 ...