【问题标题】:Can I ALTER an existing table schema using a post-deployment script?我可以使用部署后脚本更改现有表架构吗?
【发布时间】:2016-09-02 16:15:33
【问题描述】:

使用

  • SQL Server 2008(非 R2)
  • Visual Studio 2012 高级版
  • SQL Server 数据库项目/SQL Server 数据工具 (SSDT)

使用部署后脚本更改表架构是否存在任何问题\潜在问题?

我的公司有一个 Web 应用程序(应用程序 A),其后端数据库中的表使用 CDC Replication 复制到另一个公司应用程序的数据库(应用程序 B)。对这些表进行架构更改会导致 SSDT 在生成部署脚本时使用 DROP/CREATE。对于在这些表上使用 CDC Replication 的 App B 的数据库来说,这是一个问题,因为当删除并重新创建表时,App B 的数据库的 CT_[table_name] 表将被删除,从而导致 App B 停机。我的解决方案是使用部署后脚本对这些表进行更改,而不是允许 SSDT 生成 DROP/CREATE。这种方法是否存在任何潜在问题或问题?

我真的需要一些帮助。

【问题讨论】:

    标签: sql-server database sql-server-2008 visual-studio-2010 sql-server-data-tools


    【解决方案1】:

    如果您要从 SSDT 项目模型中排除这些表,您可以使用 部署后 脚本来处理此类表更改。这可以通过以下任一方式实现:

    • 对于 CDC 复制中涉及的每个表文件,将 Build Action 属性设置为
    • 或者干脆从项目中完全删除受影响的表文件

    这将阻止 SSDT 尝试对该表执行任何操作,因此您不必担心比较引擎会生成破坏您的 CDC 实例的脚本。

    当然,这意味着任何依赖于排除表对象的对象(例如过程或视图)也需要移至部署后脚本。这将导致数据库的可追溯性降低,因为所有排除的这些表将不再具有存储在源代码控制中的每个文件的历史记录。

    即使可以找到不会导致这些缺点的解决方案,例如根据 Ed 的优秀博文使用预比较脚本,也需要考虑部署原子性的问题。如果部分部署发生在 SSDT 生成的脚本中,而另一部分发生在部署后脚本中,则可能会发生错误,导致数据库处于半部署状态。这是因为 SSDT 只对它负责的部分部署使用事务;部署后脚本中包含的任何内容都将在提交初始事务后执行。

    这意味着您的部署后脚本需要以 幂等 方式编写,以便在出现问题时可以重新执行(对不起,如果这是一个明显的陈述。 .. 每当提到部署后脚本时,这似乎总是一个好点!)。

    如果需要对表更改的部署方式进行更高程度的控制,而不会损失可追溯性或部署原子性,那么我建议考虑使用迁移驱动的部署工具,例如 ReadyRoll (免责声明:我为 Redgate Software 工作)。 ReadyRoll 是 SSDT 的一个项目子类型,但使用与 SSDT 完全不同的部署风格:不是等到部署才发现表将被删除/重新创建,而是在开发时生成迁移脚本,允许更改同步在提交到源代码管理之前要进行的操作。

    有关 SSDT 和 ReadyRoll 比较的更多信息,请查看 ReadyRoll 常见问题解答: http://www.red-gate.com/library/readyroll-frequently-asked-questions-faq

    【讨论】:

    • 谢谢 Dan(iel?),您是说如果我不从 SSDT 项目模型中排除有问题的表,并且继续使用部署后脚本,SSDT 比较引擎仍将生成脚本更改架构以符合表定义? IOW,如果我有一个 SSDT 项目已知的表定义,那么稍后使用部署后脚本更改表模式(ALTER 添加一列);后续部署 SSDT 会生成一个脚本来删除我之前通过部署后脚本添加的列?
    • 顺便说一句,部署后脚本只会运行一次,而不是每次部署。
    • 没错,SSDT 比较引擎总是希望“纠正”目标数据库,使其与其世界模型一致。这意味着,如果您决定将表定义保留在项目中,并且您计划在部署后影响这些对象(例如,添加一列,如您的示例中所示),则需要遵守纪律:在每次部署到您的生产数据库之后,您需要返回并更新表定义以包含新列并将其合并回您的主分支。否则,如您所说,该列将在下一个版本中删除。
    • 好悲痛。如果源表被 DROPped 和 reCREATEd,CDC 复制端有什么可以防止删除 [table]_CT 表的吗?
    • 必须使用预比较脚本,谢谢。
    【解决方案2】:

    您是否使用内置的重构支持来重命名列/表?如果你这样做了,那么部署应该会生成一个 sp_rename。

    如果你是并且这是由于 cdc 的错误:

    • 提出一个连接项
    • 进行自己的更改,但您需要在部署之前运行脚本,否则它将为您进行所需的更改(我称之为预比较脚本)

    更多详情请见https://the.agilesql.club/Blog/Ed-Elliott/Pre-Compare-and-Pre-Deploy-Scripts-In-SSDT

    埃德

    【讨论】:

    • 谢谢埃德。似乎有很多架构更改会导致 SSDT 生成 DROP/CREATE,而不仅仅是重命名(例如,列重新排序、添加约束/列、列数据类型更改等)。在这些情况下,重构将不起作用。
    • 好的,如果你想手动做一些事情,你需要在部署之前使用你运行的脚本——我通常会在我的 cd 管道中构建一个我可以使用但没有发现我必须经常使用它们 - 诸如不断重新排序列之类的事情通常指向其他问题,例如开发人员共享开发数据库或长期运行的功能分支等
    • Ed Elliott,您的回答似乎没有直接解决我更普遍的问题,但您的博文正是我所需要的。谢谢。
    • 很高兴它有帮助!
    猜你喜欢
    • 2017-11-08
    • 1970-01-01
    • 1970-01-01
    • 2021-08-08
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2023-03-22
    相关资源
    最近更新 更多