【发布时间】:2018-03-27 14:51:04
【问题描述】:
How to add timestamps to an existing table with Ecto's timestamps? 已在此处提出此问题,但接受的解决方案意味着每个新条目都将具有相同的默认时间。我希望新条目具有正确的插入/更新时间。
例如。
# set default to given date to fill in all existing rows with timestamps
def change do
alter table(:my_table) do
timestamps(default: "2018-01-01 00:00:01")
end
end
如果这是迁移中的全部内容,则 每个 inserted_at 和 updated_at for :my_table 将具有 2018-01-01 00:00:01 作为值,无论插入/更新的日期。
我想做的是:
- 为预先存在的行向inserted_at 和updated_at 列添加日期时间。
-
inserted_at和updated_at应该是null: false,因为它们在向新创建的表中添加时间戳时是这样的。 - 未来的条目应该具有正确的inserted_at 和 updated_at 值,即inserted_at 是创建行的时间,updated_at 是更改行的时间,而不是迁移中的默认设置。
我有几个解决方案可以实现这一点,但它们看起来很混乱。我正在寻找是否有更清洁的方法来执行此操作,或者是否有处理我遗漏的这种情况的选项。
工作迁移 1:
def up do
alter table(:my_table) do
timestamps(default: "now()")
end
execute("ALTER TABLE my_table ALTER COLUMN inserted_at SET DEFAULT now()")
execute("ALTER TABLE my_table ALTER COLUMN updated_at SET DEFAULT now()")
end
def down do
alter table(:my_table) do
remove :inserted_at
remove :updated_at
end
end
工作迁移 2:
def up do
alter table(:my_table) do
timestamps(null: true)
end
execute("UPDATE my_table SET inserted_at = now()")
execute("UPDATE my_table SET updated_at = now()")
alter table(:my_table) do
modify :inserted_at, :naive_datetime, null: false
modify :updated_at, :naive_datetime, null: false
end
end
def down do
alter table(:my_table) do
remove :inserted_at
remove :updated_at
end
end
【问题讨论】:
-
我认为到目前为止您所做的是更新已添加字段的最佳解决方案。
-
或者您可以使用默认值,并且每次必须将列添加到表中时,您将明确添加插入和更新的字段。
-
你应该知道,这个功能是故意不支持的,因为 MySQL 不支持 read after writes,所以如果你的 ecto 模型和数据库在运行时可能会不同步。见José's comment here
标签: elixir phoenix-framework ecto