如何使用Ecto的时间戳为现有表添加时间戳?

Phi*_*ren 8 elixir ecto

既然inserted_atupdated_at不可能null这不起作用:

def change do
  alter table(:channels) do
    timestamps
  end
end
Run Code Online (Sandbox Code Playgroud)

** (Postgrex.Error) ERROR (not_null_violation): column "inserted_at" contains null values

有没有一种简单的方法来实现这一点而不复制timestamps'功能?

jos*_*mrb 10

timestamps/1函数接受选项关键字列表,您可以使用它设置默认值.

def change do
  alter table(:channels) do
    timestamps default: "2016-01-01 00:00:01", null: false
  end
end
Run Code Online (Sandbox Code Playgroud)


更新Ecto> = 2.1
您需要使用新类型NaiveDateTime

def change do
  alter table(:channels) do
    timestamps default: ~N[2017-01-01 00:00:01], null: false
  end
end
Run Code Online (Sandbox Code Playgroud)

如果您有更多疑问,请查看文档

  • 原始解决方案刚刚在Ecto 3.2中运行:) ...`timestamps default:"2016-01-01 00:00:01",null:false` - 这是原始的未更新答案. (2认同)

den*_*lin 5

我使用以下迁移将时间戳添加到现有表并用当前时间填充它们:

defmodule MyApp.AddTimestampsToChannels do
  use Ecto.Migration

  def up do
    alter table(:channels) do
      timestamps null: true
    end

    execute """
    UPDATE channels
    SET updated_at=NOW(), inserted_at=NOW()
    """

    alter table(:channels) do
      modify :inserted_at, :utc_datetime, null: false
      modify :updated_at, :utc_datetime, null: false
    end
  end

  def down do
    alter table(:channels) do
      remove :inserted_at
      remove :updated_at
    end
  end
end
Run Code Online (Sandbox Code Playgroud)

还有其他方法可以做到。例如,如果您有一些相关表,您可以从中借用初始时间戳:

execute """
UPDATE channels
SET inserted_at=u.inserted_at,
    updated_at=u.updated_at
FROM
  (SELECT id,
          inserted_at,
          updated_at
   FROM accounts) AS u
WHERE u.id=channels.user_id;
"""
Run Code Online (Sandbox Code Playgroud)