Sql server 将大型XML导入SQL Server表的最快方法
我有一个非常大而且不漂亮的XML,我想将它导入我的sql server数据库。XML的格式就像我说的非常难看:Sql server 将大型XML导入SQL Server表的最快方法,sql-server,xml,tsql,xquery,openrowset,Sql Server,Xml,Tsql,Xquery,Openrowset,我有一个非常大而且不漂亮的XML,我想将它导入我的sql server数据库。XML的格式就像我说的非常难看: <myxml xmlns="http://somenamespace.whatever.com/schemas/xmldata/1/" xmlns:xs="http://www.w3.org/2001/XMLSchema-instance"> <mydata> <item>
<myxml xmlns="http://somenamespace.whatever.com/schemas/xmldata/1/" xmlns:xs="http://www.w3.org/2001/XMLSchema-instance">
<mydata>
<item>
<record>some</record>
<record>123</record>
<record xs:nil="true" />
<record>random</record>
<record>234</record>
</item>
<item>
<record>345</record>
<record>in all</record>
<record>these</record>
<record>cells</record>
<record>123asdf</record>
</item>
<item>
<record>how</record>
<record>to</record>
<record>import</record>
<record>987654321</record>
<record xs:nil="true" />
</item>
</mydata>
</myxml>
我可以使用以下代码完成此操作:
CREATE TABLE XmlTable
(
XMLData XML
)
INSERT INTO XmlTable(XMLData)
SELECT CONVERT(XML, BulkColumn)
FROM OPENROWSET(BULK 'D:\myverylarge.xml', SINGLE_CLOB) AS x;
DECLARE @XML AS XML
SELECT @XML=XMLData FROM XmlTable
;WITH XMLNAMESPACES ('http://www.w3.org/2001/XMLSchema-instance' as xs, DEFAULT 'http://somenamespace.whatever.com/schemas/xmldata/1/')
INSERT INTO DataFromXml(Column1, Column2, Column3, Column4, Column5)
SELECT ref.value('record[1][not(@xs:nil = "true")]' ,'varchar(100)') as Column1
,ref.value('record[2][not(@xs:nil = "true")]' ,'varchar(100)') as Column2
,ref.value('record[3][not(@xs:nil = "true")]' ,'varchar(100)') as Column3
,ref.value('record[4][not(@xs:nil = "true")]' ,'varchar(100)') as Column4
,ref.value('record[5][not(@xs:nil = "true")]' ,'varchar(100)') as Column5
FROM @XML.nodes('/myxml/mydata/item') xmlData( ref )
这会运行一到两分钟,这可能不会太糟糕。我没有一个好的推荐人。我的感觉是,这可能要快得多,因为使用OPENROWSET将XML(超过100MB)输入数据库只需几秒钟
我可以优化insert吗?如果可以,我该怎么做?处理空值在XML中很特别 XML中空值的定义不存在。所以 您可以专门查询
text()
节点
.value('(/a/b/text())[1]','nvarchar(100)')
在这里,您可以找到一个可能的答案(有点隐藏):如果专门查询text()
节点,您可以在不使用NULL检查谓词的情况下执行所有代码
改变这个
ref.value('record[1][not(@xs:nil = "true")]' ,'varchar(100)')
对此
ref.value('(record[1]/text())[1]' ,'varchar(100)')
什么可能会打破这一点:如果
的内容可能是一个空字符串,那么您将得到一个NULL
,而不是'
。但它应该快得多。。。希望,这对你来说没问题
关于性能:阅读答案。它很好地涵盖了你的问题。特别是消耗时间的部分(请遵循此答案中的链接)。处理空值在XML中很特别 XML中空值的定义不存在。所以 您可以专门查询
text()
节点
.value('(/a/b/text())[1]','nvarchar(100)')
在这里,您可以找到一个可能的答案(有点隐藏):如果专门查询text()
节点,您可以在不使用NULL检查谓词的情况下执行所有代码
改变这个
ref.value('record[1][not(@xs:nil = "true")]' ,'varchar(100)')
对此
ref.value('(record[1]/text())[1]' ,'varchar(100)')
什么可能会打破这一点:如果
的内容可能是一个空字符串,那么您将得到一个NULL
,而不是'
。但它应该快得多。。。希望,这对你来说没问题
关于性能:阅读答案。它很好地涵盖了你的问题。特别是消耗时间的部分(按照本答案中的链接)。只是为了补充@Shnugo-answer 一切功劳都归于他 这就是您的SQL语句。它将使您的性能提高20%左右。请试一试
;WITH XMLNAMESPACES ('http://www.w3.org/2001/XMLSchema-instance' as xs, DEFAULT 'http://somenamespace.whatever.com/schemas/xmldata/1/')
INSERT INTO DataFromXml(Column1, Column2, Column3, Column4, Column5)
SELECT ref.value('(record[1]/text())[1]' ,'varchar(100)') as Column1
,ref.value('(record[2]/text())[1]' ,'varchar(100)') as Column2
,ref.value('(record[3]/text())[1]' ,'varchar(100)') as Column3
,ref.value('(record[4]/text())[1]' ,'varchar(100)') as Column4
,ref.value('(record[5]/text())[1]' ,'varchar(100)') as Column5
FROM @XML.nodes('/myxml/mydata/item') xmlData(ref);
只是为了补充@Shnugo的答案 一切功劳都归于他 这就是您的SQL语句。它将使您的性能提高20%左右。请试一试
;WITH XMLNAMESPACES ('http://www.w3.org/2001/XMLSchema-instance' as xs, DEFAULT 'http://somenamespace.whatever.com/schemas/xmldata/1/')
INSERT INTO DataFromXml(Column1, Column2, Column3, Column4, Column5)
SELECT ref.value('(record[1]/text())[1]' ,'varchar(100)') as Column1
,ref.value('(record[2]/text())[1]' ,'varchar(100)') as Column2
,ref.value('(record[3]/text())[1]' ,'varchar(100)') as Column3
,ref.value('(record[4]/text())[1]' ,'varchar(100)') as Column4
,ref.value('(record[5]/text())[1]' ,'varchar(100)') as Column5
FROM @XML.nodes('/myxml/mydata/item') xmlData(ref);
“因为使用OPENROWSET将XML(超过100MB)输入数据库只需几秒钟。”-确定吗?或者“在不进行任何解析的情况下读取文件”需要几秒钟的时间。您在那里进行了大量的处理,而OPENROWSET没有这样做。一点也不喜欢。我从来没有比较过,但你也可以试试OpenXml()。“因为使用OPENROWSET将XML(超过100MB)输入数据库只需要几秒钟。”-确定吗?或者“在不进行任何解析的情况下读取文件”需要几秒钟的时间。您在那里进行了大量的处理,而OPENROWSET没有这样做。一点也不喜欢。我从来没有比较过,但你也可以试试OpenXml()。Thx,Yitzhak,我的功劳归于你,+1来自我这边:-)谢谢@Shnugo和Yitzhak。我一定会试试的。那么插入到如何,我们能用更有效的语句替换它吗?@Stackberg,
INSERT
语句没有问题。Thx,Yitzhak,我的功劳归你,+1来自我这边:-)谢谢@Shnugo和Yitzhak。我一定会试试的。那么INSERT INTO呢?我们能用更有效的语句来代替它吗?@Stackberg,INSERT
语句没有问题。