Sql server OPENROWSET BCP Bulk Import OUTPUT子句适用于开发系统SQL Server 2016,但在SQL Server 2014的生产中失败

Sql server OPENROWSET BCP Bulk Import OUTPUT子句适用于开发系统SQL Server 2016,但在SQL Server 2014的生产中失败,sql-server,tsql,merge,sql-server-2014,sql-server-2016,Sql Server,Tsql,Merge,Sql Server 2014,Sql Server 2016,我想我这里的问题只是SQL Server版本,但我仍然需要解决或修复。我现在做的很简单 我有一个使用OPENROWSET的大容量导入,它填充临时表暂存表,该临时表是通过执行以下操作设置的: select top 0 * into ##Person from tbl_Person 根据现有物理表获取其列结构。那很好。这将引入名为ID的主键字段,它不是索引字段 然后,我通过对带有BCP格式文件XML的.csv文件执行OPENROWSET查询来填充Person。这也行得通。下一步执行合并,将临时

我想我这里的问题只是SQL Server版本,但我仍然需要解决或修复。我现在做的很简单

我有一个使用OPENROWSET的大容量导入,它填充临时表暂存表,该临时表是通过执行以下操作设置的:

select top 0 * 
into ##Person 
from tbl_Person
根据现有物理表获取其列结构。那很好。这将引入名为ID的主键字段,它不是索引字段

然后,我通过对带有BCP格式文件XML的.csv文件执行OPENROWSET查询来填充Person。这也行得通。下一步执行合并,将临时表中新获取的数据移动到原始物理表中

然后,我使用MERGE语句中的OUTPUT子句将tbl_Person物理表中的新ID值作为外键值插入另一个物理表中。这就是问题所在。在运行VS 2017和SQL Server 2016 developer edition的我的开发系统上,整个系统运行良好。但是,在生产服务器SQL server 2014 Express上,您可能会猜到:

我想让它在SQL Server 2014上运行,而不必重写整个过程。也许如果我修改OUTPUT子句,或者在正确的位置设置INSERT。我已经尝试从Person temp表中实际删除ID主键而不是索引,但没有效果

以下是被截断的代码:

USE [thedb]
GO

SET ANSI_NULLS ON
GO

SET QUOTED_IDENTIFIER ON
GO

ALTER PROCEDURE [dbo].[sp_BulkMergeDynamic] 
     @OrganisationID int, @DF nvarchar(1024), @FF nvarchar(1024)
AS
BEGIN
    SET NOCOUNT ON;

    IF OBJECT_ID('tempdb..##Person') IS NOT NULL
    DROP TABLE ##Person

    --SET IDENTITY_INSERT ##Person OFF - Requires table creation then alter table, which might be the solution
    select top 0 * into ##Person from tbl_Person 
    --GO 
    ALTER TABLE ##Person NOCHECK CONSTRAINT all 
    ALTER TABLE ##Person ALTER COLUMN DateCreated DateTime NULL 

    DECLARE @SQL NVARCHAR(MAX) = ''
    SET @SQL = 'INSERT INTO ##Person (tpp.RecordTitle, tpp.SecurityCode, ... truncated
SELECT CONCAT(tpp.FirstName, '' '', tpp.LastName), tpp.SecurityCode, ...truncated
FROM OPENROWSET(BULK''' + @DF + ''', FORMATFILE=''' + @FF + ''' ) tpp'

ALTER TABLE ##Person CHECK CONSTRAINT all

     EXEC sp_executesql @SQL

    -- SET IDENTITY_INSERT tbl_Person ON
    --ALTER TABLE tbl_Person ALTER COLUMN DateCreated DateTime NULL
    SET IDENTITY_INSERT tbl_Person OFF
    SET IDENTITY_INSERT tbl_OC OFF
    alter table ##Person drop column ID
    MERGE INTO tbl_Person AS tgt USING ##Person AS src
       ON tgt.EmailAddress1=src.EmailAddress1

    WHEN NOT MATCHED then 
    insert values(src.RecordTitle, src.SecurityCode, GETDATE(), src.FK_User_CreatedBy, ... truncated)
    --SET IDENTITY_INSERT tbl_Person OFF
           --VVVVVVVVV The problem seems to be here in SQL Server 2104 only. SQL Server 2016 developer executes with the right results in output tables.
    OUTPUT inserted.ID, inserted.EmailAddress1, @OrID, 1 INTO tbl_OC(FK_Person, RecordTitle, FK_Or, IsrID);-- output inserted.*; --@PersonTempID;

    drop table ##Person
END

GO

问题:您问题中的merge语句是完整的SQL语句,还是您的真实脚本中有其他子句?我没有看到任何东西可以保证使用merge语句。一个简单的插入到tbl_的人。。。选择从不存在的作为pt的人员中选择1,从tbl_作为p的人员中选择1,其中p.EmailAddress1=pt.EmailAddress1。除非我遗漏了什么?根据Microsoft文档,Merge应该是更简洁、更灵活的替代方法,但我可以尝试insert方法,只要它适当地处理主键字段。合并允许我从导入中跟踪和更新主键,并使用match语句避免重复。因此,我想知道如何解决合并输出和ID插入出现的特定问题。为了简洁和知识产权,它不是完整的语句(按truncates),但在没有数据的情况下也不能运行它。当然,SQL merge在只能使用merge语句执行这些操作的情况下是灵活的。即,您有一个或多个where[非]匹配子句。如果您只有一个这样的条款,在我看来,最好坚持使用基本的insert/update/delete语句。因为在这种情况下,你没有融入到陈述的真正精神中。然后你只需要插入、更新或删除。好的。这是伟大的TT和感谢,我可能会尝试它的目的是测试。同时,根据实际问题,是否有人知道如何实际解决/回答问题。合并语句?保持合并的一个原因是,我必须完全按照建议对其进行扩展,以获得更多匹配子句和进一步的输出语句,包括嵌套和动态SQL exec调用,因此我需要知道如何使SQL 2014的语句与SQL 2016的语句一样工作。有人知道如何修复SQL Server 2014的合并吗?我现在在我的开发服务器和产品箱上都得到了准稳定的结果。所有SQL Server都设置为2008 Compatibility=100。使用建议的insert,我得到了完全相同的脚本,大约70%的时间通过了测试。如果从正在工作和运行的现有已安装SP创建脚本,则无法重新创建!我在列列表中获取ID/INSERT错误。奇怪的如果它是作为SP安装的,并且创建工作时没有任何更改,那么它运行正常???