这里已经问过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
和:my_table
都会有2018-01-01 00:00:01作为值,无论插入/更新的日期如何。
我想做的是:
inserted_at
和updated_at
应该是null: false
。我有几个解决方案可以实现这一目标,但它们似乎非常混乱。我正在寻找是否有更简洁的方法来做到这一点,或者是否有办法解决这个案例,我不知道。
工作迁移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
答案 0 :(得分:1)
您可以使用fragment
将SQL函数提供为默认值。该文档提供以下示例:
create table("posts") do
add :inserted_at, :naive_datetime, default: fragment("now()")
end
timestamps
seems to forward the default:
option to add
,因此在您的特定情况下,您应该可以执行以下操作:
def change do
alter table(:my_table) do
timestamps(default: fragment("now()"))
end
end
答案 1 :(得分:0)
我遇到了同样的问题。对我来说,这是由于未在Ecto模式中指定timestamps()
:
schema "my_table" do
field(:name, :string)
...
timestamps() // <- Add this here
end
迁移仅告诉您的数据库您有时间戳列。您仍然需要告诉Ecto它们存在!