在迁移中执行原始 SQL:将 SQL 语句保留为迁移中的字符串还是单独的 SQL 文件中的代码?

Tim*_*and 5 ruby sql migration postgresql ruby-on-rails

在数据库中,我有多个具有大定义的物化视图。DROP我还进行了多次迁移,这些迁移使用和语句更改了其中一些物化视图的定义CREATE。因此,我们经常会一遍又一遍地删除/重新创建相同的视图,并进行一些小的更改。这些(相当庞大的)语句现在存储在字符串中:

class MyMigrationName < ActiveRecord::Migration[5.2]

  def up
    sql = <<~SQL
      ...
      create materialized view if not exists foo_1 as ... ;
      create materialized view if not exists foo_2 as ... ;
      ...
    SQL
    execute sql
  end

  def down
    ...
  end
Run Code Online (Sandbox Code Playgroud)

我正在考虑从当前的方法切换到另一种方法,其中 SQL 代码存储在单独的 SQL 文件中,例如在db/migrate/concerns/create_foo_matviews.sql. 从文件中读取代码并从迁移内部执行代码,如下所示:

class MyMigrationName < ActiveRecord::Migration[5.2]

  def up
    execute File.read(File.expand_path('./concerns/create_foo_matviews.rb', __FILE__))
  end

  def down
    ...
  end
Run Code Online (Sandbox Code Playgroud)

这种方法的优点是:

  • 更容易看出新旧 SQL 代码之间的差异git diff(尤其重要的是,物化视图的定义很大,但迁移的实际变化相对较小)。
  • SQL 文件向 SQL 代码添加语法突出显示。
  • 如果我只更改 SQL 文件中的相关部分,复制/粘贴的代码就会更少。

这个提议的方法有什么问题吗?如果是,最大化可维护性的替代解决方案是什么?

也可以看看

Pas*_*cal 3

我会把它留在迁移中。

主要是因为迁移包含实际构成数据库更改的所有内容。您需要有两个外部 SQL 文件(updown),在我了解迁移的作用之前,我需要先搜索/查找它们。

根据您使用的编辑器,您将获得(有限的)语法突出显示 VS Code 中的 Heredoc 中的 SQL

执行自定义 SQL 的迁移看起来都一样,只是外部文件的名称不同。

您想解决什么问题?只是“笨重”的字符串?我不认为这是值得花费大量时间的问题(老实说,一旦迁移运行,您就不会再返回到它)。只是最简单的事情:heredoc 字符串中的 SQL。

还有一些 gem 允许您使用正常的迁移代码(通过添加对create_view或类似的支持)创建(物化)视图,但我不会为如此简单的东西添加额外的依赖项。

如果尚未完成,还可以考虑从schema.rb更改为Structure.sql 。

  • 我认为你的最后一句话确实是关键。`schema.rb` 或 `structural.sql` 是数据库的权威描述。`db/migrate/` 中的所有内容都应该是短暂的,您应该能够删除几个月前且已在各处运行的迁移,而不会造成任何问题。 (2认同)
  • 删除/重新创建并进行小的更改:您会更改包含 SQL 语句的基础文件并在新的迁移中再次运行它吗?如果是这样,那就有问题了,因为它可能无法从头开始运行现有的迁移。 (2认同)