【问题标题】:Insert Multiple Rows using MySQL INSERT VALUES syntax使用 MySQL INSERT VALUES 语法插入多行
【发布时间】:2013-01-22 21:26:26
【问题描述】:

我正在寻找一种特定于 ruby​​ 的解决方案来使用 INSERT..VALUES syntax 插入多行

目前我正在生成单独的插入语句,但从数据库的角度来看这是非常低效的。我发现了一些相关的问题,但不是我要找的。​​p>

示例 INSERT 语句(当前):

INSERT INTO qux SELECT 1,3,'foo';
INSERT INTO qux SELECT 4,11,'bar';
INSERT INTO qux SELECT 12,19,'baz';

INSERT multiple records using ruby on rails active record

上述问题使用 ActiveRecord 来实现我想要做的事情,但我正在寻找一种纯 ruby​​ 方法。

how do I perform transactions with ruby mysql2

上述问题使用事务来实现与我的需求相似的结果。但是,这仍然不如使用一个 INSERT VALUES 语句高效。

示例数据:

start,end,name
1,3,foo
4,11,bar
12,19,baz

INSERT VALUES 语句(需要):

INSERT INTO qux VALUES (1,3,'foo'),(4,11,'bar'),(12,19,'baz');

任何已经存在的具有此功能的 gem/代码库?

更新:我不使用也不打算在这个特定项目中使用 ActiveRecord。我直接与 MySQL 数据库进行交互,并且很想知道我的问题的任何解决方案。一种选择可能是自己构建功能;但是我不想在这里重新发明轮子。

【问题讨论】:

  • 在没有 AR 的情况下有什么方法可以做到这一点?
  • 我支持 ar-extensions 的建议,但如果您决定避免使用 ActiveRecord 并且您的数据模型足够简单,只需构建一个巨大的 SQL 字符串来执行并执行插入即可推出您自己的解决方案.

标签: mysql ruby mysql2


【解决方案1】:
INSERT INTO SomeTable ( Col1, Col2, Col3 )
SELECT Val1, Val2, Val3 FROM SomeOtherTable
UNION
SELECT 'MyProvidedVal1', 'MyProvidedVal2', 'MyProvidedVal3'
UNION
SELECT 'MyProvidedVal4', 'MyProvidedVal5', 'MyProvidedVal6'

来源:Insert multiple rows using select

【讨论】:

    【解决方案2】:

    好的,我想出了一个有点笨拙的解决方案,但它确实有效!

    在MySQL中,制作一个简单的测试表:

    CREATE TABLE `aa_test` (
      `a` int(11) unsigned NOT NULL AUTO_INCREMENT,
      `b` varchar(256) DEFAULT NULL,
      `c` varchar(256) DEFAULT NULL,
    ) ENGINE=InnoDB AUTO_INCREMENT=48 DEFAULT CHARSET=utf8;
    

    在您的 ruby​​ 代码中,将您的行组合成一个大的 honkin' 数组:

    values = [1, 'hi', 'there', 2, 'ho', 'there', 47, 'yo', 'buddy']
    

    根据您拥有的行数动态构建查询:

    query = "INSERT INTO aa_test (`a`, `b`, `c`) VALUES "
    (values.size / 3).times {|ignore|
        query << '(?,?,?),'
    }
    query.chop! # remove final comma
    client.prepare(query).execute(*values)
    

    有效!至少,在irb。 :-)

    # mysql -h*** -u*** -p*** YourDatabaseHere -e'SELECT * FROM aa_test'
    +----+------+-------+
    | a  | b    | c     |
    +----+------+-------+
    |  1 | hi   | there |
    |  2 | ho   | there |
    | 47 | yo   | buddy |
    +----+------+-------+
    

    当然,您必须跟踪 values[] 中有多少字段和行。您可以将列名保存在一个数组中,并将它们插入到查询中并为循环提供除数。

    这是我的应用程序中的动态行数示例。你只需要一个列名数组:

    col_names = ['Date', 'Receipt_type', 'Type', 'Name', 'Item', 'Num', 'Amount', 'Source', 'Destination', 'Statement_s']
    query = 'INSERT INTO sa_general_journal ('
    col_names.each do |col_name|
        query << '`' << col_name << '`,'
    end
    query.chop!
    query << ') VALUES '
    (values.size / col_names.size).times {|ignore|
        query << '('
        (col_names.size).times {|ignore|
            query << '?,'
        }
        query.chop!
        query << '),'
    }
    query.chop!
    client.prepare(query).execute(*values)
    

    请记住,准备好的语句存在服务器端限制。 max_prepared_stmt_count 限制可以排队的准备语句的数量,以减少拒绝服务攻击。如果设置为零,则不能执行任何准备好的语句。此外,如果您正在加载 BLOBS,请记住准备好的语句数据必须适合 max_allowed_packet(我的服务器上为 16MB)。我正在使用准备好的语句将 PDF 文件加载到 BLOB 中,这让我很不爽。

    我来这里是为了寻找答案,但不得不自己想出一个。我知道这是一个老问题。 (人们因为我回答老问题而跳槽!)但我希望这对像我一样通过搜索到达这里的人有用!

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2015-09-20
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-09-01
      • 2017-02-09
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多