【问题标题】:How can execute multiple statements in one query with Rails?Rails 如何在一个查询中执行多个语句?
【发布时间】:2012-08-15 13:45:38
【问题描述】:

我正在将 Ruby on Rails 与 ActiveRecord 和 PostgreSQL 结合使用。

如何执行多个 sql 查询?

我需要它来运行自定义迁移脚本,例如:

Foo.connection.execute <<-SQL.split(';').map(&:strip).join
 delete from metadata where record_type = 'Foo';
 TRUNCATE table1 RESTART IDENTITY;
 TRUNCATE table2 RESTART IDENTITY;
 delete from schema_migrations where version > '20120806120823';
SQL

我不接受来自用户的数据,所以我不担心 sql 注入。

在 MySQL 中可能是 CLIENT_MULTI_STATEMENTS 之类的东西?

来自 MySQL/PHP 文档:

CLIENT_MULTI_STATEMENTS:告诉服务器客户端可以发送 单个字符串中的多个语句(用“;”分隔)。如果这 未设置标志,禁用多语句执行。见 有关此标志的更多信息,请注意此表。

【问题讨论】:

  • 我认为在实际示例中,您正在从文件中读取脚本,因此您不能像示例中那样对每个语句循环一次 execute 而不进行狡猾的字符串拆分?如果它直接在您的代码中,您可以将语句放在一个数组中并循环它。
  • 希望编辑准确反映您的意图。如果没有,请告诉我 - 或重新编辑。
  • 就像 Craig Ringer 所说的那样 - 简单地多次调用 connection.execute 并且每次只有一个语句有什么问题?我已经这样做了很多次(有一次,在 Rails 应用程序中第一次迁移时,运行包含数十个表的遗留 SQL 模式转储)。
  • 不想进行多个网络调用。这就是我现在正在做的事情。在这种情况下,网络调用在网络上非常慢,但我可以忍受它进行删除和截断。问这个问题主要是想知道。

标签: ruby-on-rails ruby ruby-on-rails-3 postgresql activerecord


【解决方案1】:

它应该在 PostgreSQL 中开箱即用,使用 pg gem 和 rails 3.2 检查:

class Multitest < ActiveRecord::Migration
  def up
    execute <<-SQL
      create table x(id serial primary key);
      create table y(id serial primary key, i integer);
    SQL
  end

  def down
  end
end

顺便说一句,直接操作schema_migrations 看起来很奇怪。

【讨论】:

  • 谢谢,我会检查迁移代码。但是迁移如何执行工作而 ActiveRecord 没有呢?如何从 ActiveRecord 运行多个查询?
  • 但不适用于 MySQL。 ActiveRecord 的执行在 Postgres 上多次成功,在 MySQL 上失败。
【解决方案2】:

对于mysql

queries = File.read("/where/is/myqueries.sql")
# or
queries = <<-SQL
 TRUNCATE table1 RESTART IDENTITY;
 TRUNCATE table2 RESTART IDENTITY;
 delete from schema_migrations where version > '20120806120823';
SQL

queries.split(';').map(&:strip).each do |query| 
  execute(query)
end

您可能也想看到这个问题: Invoking a large set of SQL from a Rails 4 application

【讨论】:

    【解决方案3】:

    是的,你需要CLIENT_MULTI_STATEMENTS:

    database.yml:

    development:
      adapter: mysql2
      database: project_development
      flags:
        - MULTI_STATEMENTS
    

    然后在你的代码中:

    connection.execute(multistatement_query)
    # Hack for mysql2 adapter to be able query again after executing multistatement_query
    connection.raw_connection.store_result while connection.raw_connection.next_result
    

    详情请见https://stackoverflow.com/a/11246837/338859

    【讨论】:

    • 您没有阅读问题。这是针对 Postgres,而不是 MySQL。
    • 啊,是的。我的错。
    • 对我,一个 mysql 用户,在谷歌搜索一个通用的多语句问题后遇到这个答案仍然有用! :)
    • 我无法让这个 MULTI_STATEMENTS 标志起作用。公平地说,我并没有很努力。但我最终只是将我的陈述分开并在每一个上调用execute。我只有几个,所以结果很好,不需要使用 MySQL 或 ActiveRecord。
    猜你喜欢
    • 1970-01-01
    • 2014-07-24
    • 2014-03-03
    • 1970-01-01
    • 1970-01-01
    • 2017-02-02
    • 2017-01-11
    相关资源
    最近更新 更多