如何在Ecto的迁移中运行更新?

Ton*_*Han 8 elixir ecto phoenix-framework

我在我的一个项目中使用PhoenixEcto.

我想在一个表中添加一个列,我希望它是一个NOT NULL列.但是我已经有了一些已存在的数据,所以我决定添加列,将所有行更新为某个值并将列修改为NOT NULL.

我尝试了这两个代码:

  # solution 1
  def up do
    alter table(:channels) do
      add :type, :integer
      Exchat.Repo.update_all("channels", set: [type: 1])
      modify :type, :integer, null: false
    end
  end

  # solution 2
  def up do
    alter table(:channels) do
      add :type, :integer
    end
    Exchat.Repo.update_all("channels", set: [type: 1])
    alter table(:channels) do
      modify :type, :integer, null: false
    end
  end
Run Code Online (Sandbox Code Playgroud)

他们两个都没有工作,我得到的错误如下:

23::40::07.514 [info]  == Running Exchat.Repo.Migrations.AddTypeToChannels.up/0 forward

23::40::07.541 [debug] UPDATE "channels" AS c0 SET "type" = $1 [1] ERROR query=12.0ms
** (Postgrex.Error) ERROR (undefined_column): column "type" of relation "channels" does not exist
    (ecto) lib/ecto/adapters/sql.ex:383: Ecto.Adapters.SQL.execute_and_cache/7
Run Code Online (Sandbox Code Playgroud)

我不确定它是否与Ecto版本有关,但我的Ecto版本是2.0.0-rc.0.

有没有办法实现这个目标?或者我的示例代码中有什么问题?

Dog*_*ert 20

解决方案#2是正确的方法,但您需要Ecto.Migration.flush/0在第一个alter块之后添加一个调用,以确保所有更改都立即在数据库上执行,而不是排队等待稍后执行,这是默认设置.

def up do
  alter table(:channels) do
    add :type, :integer
  end
  flush()
  Exchat.Repo.update_all("channels", set: [type: 1])
  alter table(:channels) do
    modify :type, :integer, null: false
  end
end
Run Code Online (Sandbox Code Playgroud)