【问题标题】:Conditional SQL block evaluated even when it won't be executed即使不会执行条件 SQL 块也会被评估
【发布时间】:2016-07-02 15:20:09
【问题描述】:

我正在为数据库编写迁移脚本,并希望使其具有幂等性,因此我们可以安全地运行它任意次数,而不必担心它会在第一次尝试后更改数据库(/迁移数据) .

此迁移的一部分涉及从表中删除列,但首先将该数据插入到另一个表中。为此,我有一些类似的东西。

IF EXISTS
    (SELECT * FROM sys.columns 
      WHERE object_id = OBJECT_ID('TableToBeModified')
        AND name = 'ColumnToBeDropped')
BEGIN
    CREATE TABLE MigrationTable (
        Id int,
        ColumnToBeDropped varchar
    );

    INSERT INTO MigrationTable
    (Id, ColumnToBeDropped)
    SELECT Id, ColumnToBeDropped
      FROM TableToBeModified;
END

第一次通过,这工作正常,因为它仍然存在。但是,在随后的尝试中,它失败了,因为该列不再存在。我知道对整个脚本进行了评估,我可以将内部内容放入 EXEC 语句中,但这真的是解决这个问题的最佳解决方案,还是有另一个仍然可能“强制执行有效性”的选项?

【问题讨论】:

  • 另一种选择是将 CREATE 和 INSERT 放入 sp。
  • 动态 SQL 比抽象成存储过程更简单。
  • @Balde 我同意 Aaron 的观点,尤其是因为这是一个一次性脚本,而且您仍然需要该存储过程的推出脚本,因此不会真正保存任何内容。
  • @srutzky 我同意。只是说“另一种选择”。
  • @Balde SP 也经过验证,对吧?那么这不会有同样的问题吗?

标签: sql-server database-migration


【解决方案1】:

我知道整个脚本都会被评估,我可以将内部内容放入EXEC 语句中,但这真的是解决这个问题的最佳方法吗

是的。由于脚本中其他地方的依赖关系,有几种情况您希望推迟解析验证。即使当前没有问题,我什至有时会将内容放入EXEC,以确保不会由于在当前推出脚本之后所做的其他更改而导致脚本的其余部分或环境发生变化发达。次要地,它有助于在视觉上分解事物。

虽然由于使用动态 SQL 可能会出现与破坏所有权更改相关的权限问题,但这对于推出脚本来说很少有问题,而且我从未遇到过问题。

【讨论】:

  • 您的论点似乎是我希望通过使用 EXEC 避免的所有事情;)even if there aren't currently, preventing future - 这不是注定要失败吗?将其放入 exec 意味着在实际执行之前不会对其进行评估,因此您会遇到意外的运行时失败。
  • permissions issues -- 如果权限再次更改,则在发生运行时故障之前不会明显。
  • break things up visually -- 这不是什么大问题,但我为什么要这样呢?另外,它没有经过语法测试,所以有错别字。
  • 我不是说你错了,我只是特别关心这些事情。感觉就像采用“强类型 sql”并删除好的部分,比如强类型。
  • @shortstuffsushi 这里真的没什么好担心的,而且,无论如何,你也无能为力。权限只是一个技术细节,但与推出脚本无关,因为无论如何您都需要使用特权帐户执行。
【解决方案2】:

如果我们不确定该脚本是否可以工作或是否专门迁移数据库。

但是,对于更新数据相关更改的查询,我将使用 BEGIN TRAN 执行脚本并预期检查结果然后我们需要执行 COMMIT TRAN 否则 ROLLBACK事务,所以它会丢弃事务。

【讨论】:

  • 我不确定您是否理解我在这里的要求。我不是要“测试”一个特定的事务,而是要创建一个可以运行 N 次的脚本,在第一次之后,该列将肯定不存在.它也不会手动执行,fwiw,所以我不确定事务将如何帮助它。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-10-25
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多