Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/xml/15.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
SQL 2005和SQL 2008在使用XML插入多行方面的差异_Xml_Sql Server 2005_Sql Server 2008 - Fatal编程技术网

SQL 2005和SQL 2008在使用XML插入多行方面的差异

SQL 2005和SQL 2008在使用XML插入多行方面的差异,xml,sql-server-2005,sql-server-2008,Xml,Sql Server 2005,Sql Server 2008,可能重复: 我使用以下SQL代码在表中插入多行数据。使用XML变量将数据传递到存储过程: INSERT INTO MyTable SELECT SampleTime = T.Item.value('SampleTime[1]', 'datetime'), Volume1 = T.Item.value('Volume1[1]', 'float'), Volume2 = T.Item.value('Volume2[1]', 'float') FR

可能重复:

我使用以下SQL代码在表中插入多行数据。使用XML变量将数据传递到存储过程:

INSERT INTO MyTable
   SELECT SampleTime = T.Item.value('SampleTime[1]', 'datetime'),
          Volume1 = T.Item.value('Volume1[1]', 'float'),
          Volume2 = T.Item.value('Volume2[1]', 'float')
   FROM @xml.nodes('//Root/MyRecord') T(item)
我有一大堆的单元测试来验证我是否插入了正确的信息、正确的记录数等等。。当我调用存储过程时

一切都很好,也就是说,直到我们开始胡闹数据库的兼容性级别

只要我们将DB的兼容性级别保持在90(SQL 2005),上面的代码就工作得很好。 当我们将兼容性级别设置为100(SQL 2008)时,单元测试失败,因为使用上述代码的存储过程超时

单元测试正在删除数据库,从脚本重新创建数据库,并在全新的数据库上运行测试,因此我认为这不是“旧的兼容性级别”的问题

使用SQLManagementStudio,我编写了一个快速测试SQL脚本。使用相同的XML块,我改变DB compat级别,截断表,然后使用上面的代码插入650行。当级别为90(SQL 2005)时,它以毫秒为单位运行。当级别为100(SQL 2008)时,它有时需要一分钟,有时以毫秒为单位运行

我很感激任何人对此有任何见解


编辑 脚本用我的实际数据运行需要一分钟,它的行数比我在这里显示的要多,是一个真实的表,并且有一个索引。 在下面的示例代码中,差异在毫秒和大约5秒之间

--use [master]
--ALTER DATABASE MyDB SET compatibility_level =100

use [MyDB]

declare @xml xml

set @xml = '<?xml version="1.0"?>
<Root xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
  <Record>
    <SampleTime>2009-01-24T00:00:00</SampleTime>
    <Volume1>0</Volume1>
    <Volume2>0</Volume2>
  </Record>
..... 653 records, sample time spaced out 4 hours ........
</Root>'

DECLARE @myTable TABLE(
ID int IDENTITY(1,1) NOT NULL,
    [SampleTime] [datetime] NOT NULL,
    [Volume1] [float] NULL,
    [Volume2] [float] NULL)

INSERT INTO @myTable
    select 
        T.Item.value('SampleTime[1]', 'datetime') as SampleTime,
            Volume1 = T.Item.value('Volume1[1]', 'float'),
            Volume2 = T.Item.value('Volume2[1]', 'float')
    FROM @xml.nodes('//Root/Record') T(item)
——使用[master]
--ALTER DATABASE MyDB集合兼容性\u级别=100
使用[MyDB]
声明@xml
set@xml=
2009-01-24T00:00:00
0
0
..... 653条记录,采样时间间隔为4小时。。。。。。。。
'
声明@myTable表(
ID int标识(1,1)不为空,
[SampleTime][datetime]不为空,
[Volume1][float]空,
[Volume2][float]NULL)
插入@myTable
挑选
T.Item.value('SampleTime[1],'datetime')作为SampleTime,
Volume1=T.Item.value('Volume1[1],'float'),
Volume2=T.Item.value('Volume2[1],'float')
来自@xml.nodes('//Root/Record')T(项)
我取消注释顶部的两行,选择它们并运行它(alterdatabase语句),然后注释这两行,取消选择任何文本并运行整个过程

当我从90变为100时,它会在5秒钟内一直运行(我更改了一次级别,但我运行了几次系列以查看是否有一致的结果)。 当我从100变为90时,它一直以毫秒为单位运行。 只是为了让你也能玩它。
我正在使用SQL Server 2008 R2标准版。

顺便说一句,遇到此问题的任何其他人都可能会发现这有一定的用处。根据兼容性设置,查询的x-path部分的公式化方式的细微差异可能会对性能产生很大影响


起初,我找不到关于兼容性设置为何会显著改变性能的完整解释,但从那时起,Martin Smith的回答和Microsoft Connect网站上的报告解释说,这很可能是SQL 2008中的一个缺陷,我使用的兼容性设置有一个修补程序以及其他一些解决方法SQLServerCentral上的原始链接就是其中之一。

这是SQLServer2008中的一个错误

如本程序所示,可通过启用TraceFlag 4130进行修复

USE [MyDB]

--Comment / Uncomment the next two lines as appropriate to test the effect with the TF turned on or off
DBCC TRACEON(4130,-1)
--DBCC TRACEOFF(4130,-1)

GO
DBCC FREEPROCCACHE
GO
declare @xmlstring varchar(max) = '<?xml version="1.0"?>
<Root xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">'

SELECT @xmlstring += 
  '<Record>
    <SampleTime>2009-01-24T00:00:00</SampleTime>
    <Volume1>0</Volume1>
    <Volume2>0</Volume2>
  </Record>'
FROM master..spt_values  
WHERE type='P' AND number BETWEEN 1 AND 653

set @xmlstring += '</Root>'

DECLARE @xml xml =  @xmlstring
SELECT @xml

DECLARE @myTable TABLE(
ID int IDENTITY(1,1) NOT NULL,
    [SampleTime] [datetime] NOT NULL,
    [Volume1] [float] NULL,
    [Volume2] [float] NULL)

INSERT INTO @myTable
    select 
        T.item.value('SampleTime[1]', 'datetime') as SampleTime,
            Volume1 = T.item.value('Volume1[1]', 'float'),
            Volume2 = T.item.value('Volume2[1]', 'float')
    FROM @xml.nodes('//Root/Record') T(item)
使用[MyDB]
--根据需要注释/取消注释下两行,以测试TF打开或关闭时的效果
DBCC跟踪(4130,-1)
--DBCC TRACEOFF(4130,-1)
去
DBCC FREEPROCCACHE
去
声明@xmlstring varchar(max)='
'
选择@xmlstring+=
'
2009-01-24T00:00:00
0
0
'
从主..spt_值
其中type='P'和数字介于1和653之间
设置@xmlstring+=“”
声明@xml=@xmlstring
选择@xml
声明@myTable表(
ID int标识(1,1)不为空,
[SampleTime][datetime]不为空,
[Volume1][float]空,
[Volume2][float]NULL)
插入@myTable
挑选
T.item.value('SampleTime[1],'datetime')作为SampleTime,
Volume1=T.item.value('Volume1[1],'float'),
Volume2=T.item.value('Volume2[1],'float')
来自@xml.nodes('//Root/Record')T(项)

相关项目中提到了各种其他解决方法。

您是想修复它,还是只想了解它为什么会改变?我想了解并修复它我还没有机会弄清楚如何修复它(或它为什么会发生),但在compat 100 for me中时,查询计划会为每个表值函数生成额外的表假脱机-这将考虑所需的额外时间,因为这些值正在写入tempdb。如果我提出了一个解决方案,我会给出一个答案——但如果我找不到时间或解决方案,希望这可以为您指明正确的方向:)。不过,这是一个伟大的发现!这是一个已知的错误,请参阅我的答案以了解详细信息。谢谢Martin,我将把我的答案保留在这里以供参考。不过,希望人们在投票时能轻松一点;)谢谢你。我在一个MSDTC事务超时(1分钟)的客户站点遇到了这个问题。我不知道这个bug,但使用
text()
获取值修复了它。起初,我无法在安装时复制此内容,但我发现它在某种程度上取决于“最大服务器内存”设置。例如,在2GB服务器上使用500 MB的值不会有任何问题。将最大内存设置为700,上述代码需要5秒而不是53毫秒。@MikaelEriksson-很有趣。不知道为什么会有影响。在执行计划属性中,“提前终止声明的原因”是什么?在fast的情况下是“超出内存限制”吗?如果是这样的话,也许它从来没有考虑过