如何使用dacpac和SqlPackage.exe部署时态表

时间:2018-03-30 15:36:47

标签: sql-server sql-server-data-tools dacpac temporal

我们正在尝试使用SQL Server 2016中的时态表。我们正在Visual Studio 2017中开发SSDT 15.1.6中的SQL脚本,但是在尝试部署构建期间生成的dacpac时遇到了问题。

我们的dacpac是使用SqlPackage.exe部署的,我们在尝试部署dacpac时遇到此错误:

  

创建[dbo]。[TestHISTORY]。[ix_TestHISTORY] ...
  批处理执行时发生错误   更新数据库(失败)
  无法部署包。
  错误SQL72014:.Net SqlClient数据提供程序:

     

Ms 1913,Level 16,State 1,Line 1
  操作失败,因为表'dbo.TestHistory'上已存在名为'ix_TestHISTORY'的索引或统计信息。

     

错误SQL72045:脚本执行错误。执行的脚本:
          创建聚集索引[ix_TestHISTORY]               ON [dbo]。[TestHistory]([SysStart] ASC,[SysEnd] ASC);

当我们在SSDT中创建时态表时,我们有以下内容:

CREATE TABLE [dbo].[Test]
(
    [Id] INT NOT NULL PRIMARY KEY,
    [SysStart] DATETIME2 (7) GENERATED ALWAYS AS ROW START NOT NULL,
    [SysEnd] DATETIME2 (7) GENERATED ALWAYS AS ROW END NOT NULL,
    PERIOD FOR SYSTEM_TIME ([SysStart], [SysEnd])
)
WITH (SYSTEM_VERSIONING = ON(HISTORY_TABLE=[dbo].[TestHISTORY], DATA_CONSISTENCY_CHECK=ON))

据我所知,这个问题与dacpac创作有关。项目构建完成后,创建的dacpac如下所示:

CREATE TABLE [dbo].[test]  
(
    [Id]       INT NOT NULL PRIMARY KEY CLUSTERED ([Id] ASC),
    [SysStart] DATETIME2 (7) GENERATED ALWAYS AS ROW START NOT NULL,
    [SysEnd]   DATETIME2 (7) GENERATED ALWAYS AS ROW END   NOT NULL,
    PERIOD FOR SYSTEM_TIME ([SysStart], [SysEnd])
)
WITH (SYSTEM_VERSIONING = ON (HISTORY_TABLE=[dbo].[testHISTORY], DATA_CONSISTENCY_CHECK=ON));
GO

CREATE TABLE [dbo].[testHISTORY] 
(
    [Id]       INT           NOT NULL,
    [SysStart] DATETIME2 (7) NOT NULL,
    [SysEnd]   DATETIME2 (7) NOT NULL
);
GO

CREATE CLUSTERED INDEX [ix_testHISTORY]
    ON [dbo].[testHISTORY]([SysEnd] ASC, [SysStart] ASC);
GO

我怀疑因为我们正在使用temporal table with a default history table我们不能让dacpac创建那些额外的创建语句。由于这有效地导致SQL Server尝试两次创建这些项目,导致上述错误。

有谁知道我们可能缺少什么?或者,如果您使用dacpac部署时态表,那么使用user-defined history tables是唯一的选择吗?

2 个答案:

答案 0 :(得分:3)

我们在时态表和DACPAC之间存在许多问题。一些提示将会有很长的路要走:

  • 明确声明历史记录表 - 这比人们想象的更进一步。添加/删除列时,您可以在历史记录表上定义默认值,从而可以绕过表中已存在数据时出现的许多问题。
  • 将默认值添加到一切 - 这不容小觑。默认值是DACPAC的最佳朋友。
  • 查看脚本 - 很高兴将DACFx视为手动,但事实并非如此。偶尔复习一下这些剧本,你会获得很多洞察力(看起来你已经是!)
  • 明确命名您的索引 - DACFx有时会使用索引/表格/其他内容的临时名称。一致性是王道,对吗?
  • 查看所有发布配置文件选项 - 有时,您在配置文件中没有想到的设置。在我们意识到发布配置文件中存在事务脚本设置之前,我们花了很多人工干预。

还要了解谁将您的DACPAC转换为脚本。 VS使用SqlPackage.exe,但我有时会从DACFx DLL获得不同的结果。它可能是两者之间不同的配置,但很难找到。试试两者,看看是否效果更好。

祝你好运!希望这有帮助!

答案 1 :(得分:0)

您可以尝试的一个潜在的hacky工作是预部署脚本;

https://msdn.microsoft.com/en-us/library/jj889461(v=vs.103).aspx

它们在“部署脚本生成”和“部署脚本”之间执行。 '执行部署脚本'。因此,如果您无法避免索引名称上的冲突,您可以在升级之前重命名现有索引,这很hacky,我假设您正在部署/更新实时数据库的模式而不是创建新数据库

BTW,列名称'ValidFrom'和& 'ValidTo'在错误消息中找到?,如果它是自动生成的那么它应该是'SysEnd'& 'SYSSTART'