2017-02-10 3 views
3

Я ищу самый простой способ экспортировать таблицу (или ее часть) в XML-файл, а затем импортировать этот XML-файл в соответствующую таблицу в другой базе данных.Как написать `select ... FOR XML` запросы, которые генерируют xml и xsd так, что они готовы к работе с SQLXMLBulkLoad?

Принцип я нашел очень простой:

  1. Экспорт: на исходной базе данных я генерировать строку XML, а также строку схемы XSD путем добавления FOR XML root('Data') и FOR XML, XMLSCHEMA положения для выбора запроса.
  2. Импорт: в целевую базу данных Я загружаю сгенерированный XML-файл с помощью SQLXMLBulkLoad с помощью сгенерированного xsd.

Но я не могу это сделать. Между экспортом и импортом я должен внести некоторые незначительные изменения в схему 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> 

и

<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 Script, как этот

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, который действительно подходит для пакетной загрузки сгенерированного XML с помощью SQLXMLBulkLoad выглядит как это:

<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 могут быть изменены таким образом, что сгенерированного XML и XSD работы с VBScript без какого-либо ручного изменения?

+0

Это очень хорошо вопрос (+1 с моей стороны)! Ясно, с кодом, но - я сожалею об этом, но пока не ответил ... SQL-Server предлагает «XMLSCHEMA» и «XMLDATA» для создания двух разных версий мета-описания (встроенного). Это явно не соответствует вашим потребностям. Вы можете использовать строковые методы vb, чтобы изменить это. Может быть, кто-то еще знает лучше ... – Shnugo

ответ

1

Как ваш вопрос спросил, способ SIMPLEST, который может быть очень переносимым и совместимым, может использовать простые наборы данных 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, вы просто читать в базу данных TARGET, используя что-то вроде это:

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

Смежные вопросы