【问题标题】:How to execute SQL SELECT query in ecto migrations如何在 ecto 迁移中执行 SQL SELECT 查询
【发布时间】:2019-07-10 01:38:49
【问题描述】:

我正在为多租户使用 Triplex 包。当我创建一个租户时,它会执行所有迁移。创建表后,当我执行种子迁移时,它给了我错误:

{:error, "ERROR 42P01 (undefined_table) relation \"t2.tenants\" does not exist\n\n query: (SELECT MAX(id) from \"t2.tenants\")"}

关于选择查询。如果我删除选择查询,其他查询会成功执行。

defmodule TudoChat.Repo.Migrations.SeedTableTenants do
  use Ecto.Migration

  def up do
    execute("INSERT INTO t2.tenants (\"id\", \"inserted_at\", \"name\", \"status\", \"updated_at\") values ('1', '2019-07-08 10:37:28', 'tudo_', 'active', '2019-07-08 10:37:30')")
    execute("INSERT INTO t2.tenants (\"id\", \"inserted_at\", \"name\", \"status\", \"updated_at\") values ('2', '2019-07-08 10:38:19', 'test_', 'active', '2019-07-08 10:38:22')")
    execute("(SELECT MAX(id) from \"t2.tenants\")")
  end

  def down do
  end
end

请帮我如何执行选择查询?

【问题讨论】:

  • 你试过不带引号的 t2.tenants 吗? ...注意插入没有引号。无论如何,我同意@kelu-thatsal 关于尽可能使用适当的种子机制的观点。

标签: migration elixir ecto


【解决方案1】:

不要将迁移用作植入数据库的工具。如果您使用priv/repo/seeds.exs 中的默认Ecto 设置,则已经有一个包含种子的文件。在那里你可以使用 ecto 模式和Repo

例如:

  alias TudoChat.Repo
  alias TudoChat.Tenant

  Repo.insert! %Tenant{
    name: "tudo",
    status: "active"
  }

  Repo.insert! %Tenant{
    name: "test",
    status: "active"
  }

这样您就不必担心种子数据的 ID 和时间戳,因为 Ecto 会为您处理这些问题。

运行迁移后,您还必须运行另一个命令:

mix ecto.migrate
mix run priv/repo/seeds.exs

如果您确实需要在种子中运行查询,那么您也可以使用通常的 ecto 查询。

【讨论】:

  • 如果我添加一个表并且我需要在该表中有 4 个特定行怎么办?稍后在另一个迁移中,另一个表将默认为这些行之一?
【解决方案2】:

不要键入带有嵌套引号的字符串。您喜欢转义嵌套引号吗?如果不是,请使用~s|...|~s{...}~s(...)~s<....> 代替外部双引号。例如:

iex(2)> ~s|I said, "Go home!"|
"I said, \"Go home!\""

这是您使用~s sigil 的声明:

execute(~s|INSERT INTO t2.tenants ("id", "inserted_at", "name", "status", "updated_at") values ('1', '2019-07-08 10:37:28', 'tudo_', 'active', '2019-07-08 10:37:30')|)

但是那条线还是太冗长了。所以,做这样的事情:

columns = ~s|("id", "inserted_at", "name", "status", "updated_at")|
values = "('1', '2019-07-08 10:37:28', 'tudo_', 'active', '2019-07-08 10:37:30')"
query = "INSERT INTO t2.tenants #{columns} values #{values}"
IO.inspect query
execute(query)

query 是这样的:

"INSERT INTO t2.tenants 
    (\"id\", \"inserted_at\", \"name\", \"status\", \"updated_at\") 
 values 
    ('1', '2019-07-08 10:37:28', 'tudo_', 'active', '2019-07-08 10:37:30')"

请帮我如何执行选择查询?

execute("(SELECT MAX(id) from \"t2.tenants\")")

1) 您的数据库真的需要 SELECT 语句周围的括号吗?

  |                                  |
  V                                  V
 "(SELECT MAX(id) from \"t2.tenants\")" 

2) 在您成功的 INSERT 语句中,您不必引用表名。您的数据库真的需要您在 SELECT 中引用表名吗?

                        |           |
                        V           V
 "(SELECT MAX(id) from \"t2.tenants\")"

怎么样:

execute("SELECT MAX(id) from t2.tenants")

但是,execute() 如果成功则返回 :ok,所以我不确定执行该 SELECT 语句有什么帮助。你可能想看看Ecto.Adapters.SQL.query()

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-08-11
    • 1970-01-01
    • 2018-02-21
    • 2019-01-27
    • 2015-10-20
    • 2020-04-13
    相关资源
    最近更新 更多