SQL Server:使用openxml和timestamp

时间:2018-02-12 19:02:20

标签: sql sql-server tsql

好的,这是正在运作的过程

  1. 我们的生产服务器xml文件中为每个表创建的xml文件

  2. 根据导入数据的那些xml文件

  3. 生产中有一点变化。创建了一个名为RowVer的字段timestamp

    现在,在导出RowVer的xml文件中,它的值就在那里。它不仅在base64中编码,而且现在可以将显式值插入timestamp字段。

    无论如何,在存储过程中,如果表格为x且字段为y,则会有一个规则表,然后忽略它。

    基本上SQL代码是这样的:

    --declare @ImportPath varchar(1000) = 'E:\ExportTest\171026140442\' --bunch of xml files
    --declare @DB varchar(1000) = 'DestinationDb.dbo'
    --declare @debug bit = 1
    ALTER PROCEDURE [dbo].[STP_StageImp_ImportData]
        @ImportPath varchar(1000),
        @DB varchar(1000),
        @debug bit
    AS
    
    if object_id('tempdb..#Files') is not null drop table #Files
    create table #Files
    (
    ID int
    ,TableName varchar(1000)
    ,Depth int
    ,IsFile bit
    )
    
    insert into #Files (TableName, Depth, IsFile) exec xp_dirtree @ImportPath, 10, 1
    
    declare @DataTableName varchar(1000)
    declare @TargetDataTableName varchar(1000)
    declare @sql nvarchar(max)
    
    
    while (select count(*) from #Files) > 0
     begin
        set @DataTableName = (select top 1 TableName from #Files order by ID, TableName)
    
    
    
    if object_id('tempdb..#RawData') is not null drop table #RawData
    
    create table #RawData
    (
    TableName varchar(1000),
    RawXML xml
    )
    
    set @sql = ' insert into #RawData
                select ''' + parsename(@DataTableName,2) + ''', BulkColumn from openrowset(  
                bulk ''' + @ImportPath + @DataTableName + ''',  
                single_nclob) as x'
    
    
    exec (@sql)
    
    declare @XMLData xml
    select @XMLData = RawXML from #RawData
    
    declare @ColumnNames nvarchar(MAX)
    declare @ColumnSchema nvarchar(MAX)
    declare @hDoc int
    
    if object_id('tempdb..#columns') is not null drop table #columns
    create table #columns
    (
        column_name varchar(1000),
        column_full varchar(1000)
    )
    
    
    insert into #columns
    exec STP_StageImp_TableCols @TargetDataTableName
    
    
    delete from #columns where column_name IN ('ID','RowVer')
    
        delete @data
    insert into @data select c.Column_Name + ',' from #columns c
    exec STP_StageImp_MergeRows @data, @debug, @ColumnNames output
    
    
    exec sp_xml_preparedocument @hDoc output, @XMLData
    
    set @sql = N'insert into ' +  @TargetDataTableName + ' select * from openxml(@hDoc, ''table/row'') with (' + @ColumnSchema + N')'
    
    exec sp_executesql @SQL, N'@hDoc int', @hDoc
    
    exec sp_xml_removedocument @hDoc
    
    delete from #Files where TableName = @DataTableName
    end
    

    错误是

      

    服务器列名称或提供的值数与表定义不匹配

    但是这不是真的

    如果我运行select * from Destionation.dbo.Table并转储到Excel文件和表架构并进行比较

    select * from openxml(@hDoc, ''table/row'') with (' + @ColumnSchema + N')'
    

    我验证了目标表没有任何“隐藏”字段。

    如果我将其更改为

    set @sql = N'insert into ' +  @TargetDataTableName + ' (' + @ColumnNames + ')
                 select * from openxml(@hDoc, ''table/row'') with (' + @ColumnSchema + N')'
    

    (上面的差异是显式地使用@ColumnNames)这个工作

    所以最后......由于新的时间戳列,我不想将我们的flash阶段更改为QA存储过程。

    如果有人知道为什么在表格中添加timestamp列会导致insert into table select * fro openxml中断,我会很感激。

    这不是超高优先级,因为我有一个解决方法,但如果有人有任何建议发布。

1 个答案:

答案 0 :(得分:1)

错误是因为您的插入没有显式命名列。几个小时前我在评论中发布的确切警告。这很容易证明。

create table Something
(
    SomeVal int
)

insert Something
select 1

select * from Something

--at this point you have 1 row in the table

--now add the new column
alter table Something add asdf timestamp

insert Something
select 1
--whoa....it failed.

--but if I name the columns it works again.
insert Something(SomeVal)
select 1

select * from Something

您可能还会查看文档,因为timestamp数据类型已被弃用了相当长的一段时间。 https://docs.microsoft.com/en-us/sql/t-sql/data-types/rowversion-transact-sql