【问题标题】:Is it possible to refactor this MySQL stored procedure loop?是否可以重构这个 MySQL 存储过程循环?
【发布时间】:2010-11-10 15:20:03
【问题描述】:

我在 MySQL 存储过程中有一个循环,我几乎为每次迭代插入记录。众所周知的问题是逐行插入效率低下,我宁愿看到带有多个值列表的插入。

当前程序的伪示例:

CREATE PROCEDURE p_foo_bar()
BEGIN
  DECLARE foo VARCHAR(255);
  DECLARE my_cursor CURSOR FOR SELECT foo FROM bar;
  DECLARE CONTINUE HANDLER FOR NOT FOUND SET not_found = 1;

  cursor_loop:
  LOOP
    FETCH my_cursor INTO foo;

    IF not_found THEN
      CLOSE my_cursor;
      LEAVE
    END IF;

    IF foo is something ... THEN
      INSERT INTO foobar (foo_colum) VALUES (foo);

      -- Anyone knows if it is possible to do bulk insert here:
      -- For example:
      -- INSERT INTO foobar (foo_column) VALUES (foo), ..., (foo123);
    END IF;
  END LOOP cursor_loop;
END

我宁愿看到 INSERT 查询来增加它的值列表一段时间,然后定期批量插入,但如果不煮一大碗意大利面,就看不到方法。

【问题讨论】:

    标签: mysql stored-procedures loops


    【解决方案1】:

    如何构建一个准备好的语句并在循环之后执行它

    http://dev.mysql.com/tech-resources/articles/4.1/prepared-statements.html

    declare @column_names text;
    declare @column_values text;
    

    然后在循环内添加你的 变量的列名和值

    循环结束后,您可以构建查询并执行

    set @sql_text = CONCAT('INSERT INTO foobar (', @column_names, 
                     ') VALUES (', @column_values, ')';
    
    prepare stmt from @sql_text;
    
    execute stmt;
    

    乔什

    【讨论】:

    • 这个想法是在没有循环的单个插入语句中完成。此方法将花费与原始循环一样多(如果不是更多)的时间和资源。带有 select 的单个 insert 会表现得更好。
    • 我同意 - 我认为的问题是因为他们在循环中做了一些额外的事情
    • 基于 OP 的问题:我宁愿看到 INSERT 查询来增加它的值,我理解你的回答。我只是想发表评论,以便 OP 了解单个插入效率更高。
    【解决方案2】:

    这不仅仅是一个 MySQL 问题,它发生在任何相当大的 RDBMS 中(当然,不包括 Access)。您所描述的称为“设置逻辑”。什么是'if'和循环做一个好的where子句没有?源信息是否会随着时间而变化,并且循环本质上是轮询?如果这是真的,您仍然需要某种循环,但最好使用 where 子句一次插入尽可能多的行,然后创建一个循环,让您随着时间的推移进行更新。这种类型的循环可能最好不要放在存储过程之外。另一个答案已经给出了我建议的一般 SQL。

    【讨论】:

      【解决方案3】:

      您确定需要以这种方式迭代“SELECT foo FROM bar”吗...

      没有办法吗

      insert into foobar (foo_column) 
      select foo 
        from bar 
        where foo is something
      

      ??

      【讨论】:

        【解决方案4】:

        试试这个:

         INSERT INTO foobar (foo_column, , ....)
            SELECT foo, ..., foo123
            FROM bar
            WHERE foo is something ...
        

        【讨论】:

        • 我知道这样做的可能性。但是在过程中,有一些额外的决定,我很难弄清楚 INSERT ... SELECT 查询是如何适应的。到目前为止还没有运气。
        • @Priit,显示“一些额外的决定”。这将是您问题的全部要点以及需要解决的问题。
        猜你喜欢
        • 2012-07-21
        • 1970-01-01
        • 2018-05-15
        • 1970-01-01
        • 1970-01-01
        • 2013-11-13
        • 2013-08-05
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多