2017-02-10 51 views
3

我正在寻找最简单的方式将表(或其中的一部分)导出到xml文件,然后将此xml文件导入到其他数据库中的相应表中。如何编写`select ... FOR XML`查询生成一个xml和一个xsd,以便他们准备好用于SQLXMLBulkLoad?

我发现的原理很简单:

  1. 出口:源数据库我生成一个XML字符串,并且还加入了FOR XML root('Data')FOR XML, XMLSCHEMA子句选择查询XSD架构串上。
  2. 在目标数据库上导入:我使用生成的xsd通过SQLXMLBulkLoad批量生成生成的xml文件。

但我不能做到这一点。在导出和导入之间,我必须对xsd模式进行一些小修改。

例如,我产生由以下查询XML和XSD的字符串:

select top 3 * FROM myTable 
FOR XML AUTO, ELEMENTS 
,Root('Data') 

SELECT top 0 * FROM myTable 
FOR XML AUTO, ELEMENTS 
,XMLSCHEMA 

产生的generated.xml和generated.xsd看起来如此:

<Data> 
    <myTable> 
     <field1>value11</field1> 
     ... 
     <field1>value1n</field1> 
    </myTable> 
    <myTable> 
     <field1>value21</field1> 
     ... 
     <field1>value2n</field1> 
    </myTable> 
    <myTable> 
     <field1>value31</field1> 
     ... 
     <field1>value3n</field1> 
    </myTable> 
</Data> 

and

<xsd:schema 
targetNamespace="urn:schemas-microsoft-com:sql:SqlRowSet1" 
xmlns:schema="urn:schemas-microsoft-com:sql:SqlRowSet1" 
xmlns:xsd="http://www.w3.org/2001/XMLSchema" 
xmlns:sqltypes="http://schemas.microsoft.com/sqlserver/2004/sqltypes" 
elementFormDefault="qualified"> 
    <xsd:import namespace="http://schemas.microsoft.com/sqlserver/2004/sqltypes" schemaLocation="http://schemas.microsoft.com/sqlserver/2004/sqltypes/sqltypes.xsd"/> 
    <xsd:element name="myTable"> 
     <xsd:complexType> 
      <xsd:sequence> 
       <xsd:element name="field1" type="..." .../> 
       ... 
       <xsd:element name="fieldn" type="..." ... /> 
      </xsd:sequence> 
     </xsd:complexType> 
    </xsd:element> 
</xsd:schema> 

但是,如果我想通过VB脚本这样

set objBL = CreateObject("SQLXMLBulkLoad.SQLXMLBulkload.4.0") 
objBL.ConnectionString = "provider=SQLOLEDB.1;data source=localhost\SQLEXPRESS;database=Testdb;uid=sa;pwd=*****" 
objBL.ErrorLogFile = ".\error.xml" 
objBL.KeepIdentity = False 
objBL.Execute "generated.xsd", "generated.xml" 
set objBL=Nothing 

到批量加载那么这个如果我在generated.xsd进行以下修改

  • 删除此xsd:schema属性只适用: targetNamespace="urn:schemas-microsoft-com:sql:SqlRowSet1"
  • 加上此xsd:schema属性:xmlns:sql="urn:schemas-microsoft-com:mapping-schema"
  • 替换<myTable>元件由<myTable>元素的序列,整个包装成一个<xsd:element name="Data" sql:is-constant="1">元件
  • maxOccurs="unbounded" sql:relation="myTable"添加的属性的<myTable>元件

所以,修饰的XSD是真正适合于批量加载由SQLXMLBulkLoad长相生成的XML像这样:

<xsd:schema 
xmlns:sql="urn:schemas-microsoft-com:mapping-schema" 
xmlns:schema="urn:schemas-microsoft-com:sql:SqlRowSet1" 
xmlns:xsd="http://www.w3.org/2001/XMLSchema" 
xmlns:sqltypes="http://schemas.microsoft.com/sqlserver/2004/sqltypes" 
elementFormDefault="qualified"> 
    <xsd:import namespace="http://schemas.microsoft.com/sqlserver/2004/sqltypes" schemaLocation="http://schemas.microsoft.com/sqlserver/2004/sqltypes/sqltypes.xsd"/> 
    <xsd:element name="Data" sql:is-constant="1"> 
     <xsd:complexType> 
      <xsd:sequence> 
       <xsd:element name="myTable" maxOccurs="unbounded" sql:relation="myTable"> 
        <xsd:complexType> 
         <xsd:sequence> 
          <xsd:element name="field1" type="..." .../> 
          ... 
          <xsd:element name="fieldn" type="..." ... /> 
         </xsd:sequence> 
        </xsd:complexType> 
       </xsd:element> 
      </xsd:sequence> 
     </xsd:complexType> 
    </xsd:element> 
</xsd:schema> 

不知所述生成的SQL查询和/或的VBScript可以这样修改,即使用VBScript所生成的XML和XSD工作无需任何手动修改?

+0

这是一个非常好的问题(从我身边+1)!用代码清除,但是 - 我很抱歉 - 但没有回答... SQL-Server提供了“XMLSCHEMA”和“XMLDATA”来生成两种不同版本的(嵌入式)元描述。这显然不符合你的需求。你可以使用vb的字符串方法来修改它。也许别人知道得更好...... – Shnugo

回答

1

正如您的问题所述,最简单的方式可以是高度可移植且兼容的,可以像这样使用简单的XML数据集。假设你有两个SQL服务器。我在SQL> Excel,SQL> SQL,SQL> Oracle之间使用了这种方法。

你可以在SQL中,为一个存储过程调用:

DECLARE @xml xml 

SET @XML = (
SELECT field1, field2 
FROM table 
FOR XML RAW('row'), ROOT('data'), ELEMENTS 
) 

这将返回:

<root> 
    <row> 
<field1>SomeData</field1> 
<field2>SomeOtherData</field2> 
</row> 
</root> 

一旦你的XML,只需使用类似读取到目标数据库这个:

INSERT INTO TargetDatabase.TargetTable(field1, field2) 
SELECT tbl.c.value('field1','varchar(1000)'), tbl.c.value('field2','bigint') 
FROM @XML.nodes('/root[1]/row) tbl(c) 

如果需要,你也可以很容易地在传入的XML数据上运行查询等:

INSERT INTO TargetTable(field1, field2) 
SELECT tbl.c.value('field1','varchar(1000)'), tbl.c.value('field2','bigint') 
FROM @XML.nodes('/root[1]/row) tbl(c) 
WHERE tbl.c.value('field2','bigint') > 100 or tbl.c.value('field1','varchar(1000)') Like '%fish%' 

非常高效,速度非常快。不需要混淆架构。唯一的问题是字段类型是硬编码的,所以你需要定制构建每个SP读/写。

如果你有某种剂(例如MS Excel这样做),它只是写一个存储过程在目标数据库接收XML数据的简单情况:

CREATE PROCEDURE sp_target_for_XML 
@XML xml 
+0

这并不算太坏,但它并不一定是有很多领域时最简单的方法。而你的代码包含一些错误。工作代码是SELECT tbl.c.value('field1 [1]','varchar(1000)'),tbl.c.value('field2 [1]','bigint') FROM @ XML.nodes '/ root [1]/row')tbl(c)。尽管如此,它值得我的+1。 – mma