insert_all不会使用ecto 2.0创建自动生成的inserted_at

时间:2016-05-31 04:54:11

标签: elixir phoenix-framework ecto

# mix.exs
  defp deps do
    [{:phoenix, "~> 1.1.4"},
      {:postgrex, ">= 0.0.0"},
      {:phoenix_ecto, "~> 3.0.0-rc"},
      {:gettext, "~> 0.9"},
      ...
    ]
  end

已安装的ecto版本为"2.0.0-rc.5"

iex(1)> categories = [%{name: "stackoverflow", url: "stackoverflow.com"}]

iex(2)> App.Repo.insert_all App.Category, categories

** (Postgrex.Error) ERROR (not_null_violation): null value in column "inserted_at" violates not-null constraint

    table: categories
    column: inserted_at

Failing row contains (1, stackoverflow, stackoverflow.com, null, null).
    (ecto) lib/ecto/adapters/sql.ex:176: Ecto.Adapters.SQL.query!/5
    (ecto) lib/ecto/adapters/sql.ex:350: Ecto.Adapters.SQL.insert_all/8
    (ecto) lib/ecto/repo/schema.ex:42: Ecto.Repo.Schema.do_insert_all/6
iex(2)> 

从文档中,inserted_at似乎是自动生成的。我应该手动做这个部分吗?

schema "categories" do
 field :name, :string
 field :url, :string

 timestamps
end

2 个答案:

答案 0 :(得分:13)

Ecto.Schema.timestamps/1函数定义inserted_atupdated_at列。迁移中有一个具有相同名称的功能。

您可以使用以下命令在数据库级别设置:

alter table(:categories) do
  modify :inserted_at, :datetime, default: fragment("NOW()")
end

或者您可以在地图中设置它:

categories = [%{name: "stackoverflow", url: "stackoverflow.com", inserted_at: Ecto.DateTime.utc}]

无论您选择哪种解决方案,您都可能需要对updated_at执行相同操作。

如果您不想跟踪时间戳,那么您可以从架构中远程timestamps并在迁移中删除列(或者如果您尚未提交迁移到版本控制,只需删除timestamps也在那里发挥作用。

答案 1 :(得分:1)

来自insert_all documentation

  使用insert_all/3时,

... 时间戳将不会自动生成。这个   是设计,因为这个功能旨在成为一种更直接的插入方式   数据进入数据库时​​没有insert/2 ..

的便利