【问题标题】:MySQL stored procedure insert multiple rows from listMySQL存储过程从列表中插入多行
【发布时间】:2016-05-12 05:30:10
【问题描述】:

如何编写 MySQL 存储过程以从可变大小的列表中插入值?更具体地说,我需要将数据插入到一个父表中,从插入中获取 ID,然后以一对多的关系将可变数量的子记录与新 ID 一起插入到另一个表中。我的架构看起来像这样:

表A:

table_a_id -- Auto Increment
counter
some_data...

表B:

table_b_id -- Auto Increment
table_a_id -- Foreign Key Constraint
some_data_from_list...

到目前为止,我的存储过程如下所示:

DELIMITER ;;
CREATE PROCEDURE insert_group_alert(
  IN _some_data_a         VARCHAR(255),
  IN _data_list_b         TEXT,
)
  BEGIN
    DECLARE EXIT HANDLER FOR SQLEXCEPTION
    BEGIN
      ROLLBACK;
    END;
    START TRANSACTION;

    INSERT INTO TableA (
      some_data,
      counter
    )
    VALUES (
      _some_data_a,
      1
    )
    ON DUPLICATE KEY UPDATE
      counter          = counter + 1;

    SELECT last_insert_id()
      INTO @newId;

LIST INSERT ???:
    INSERT INTO TableB (
      table_a_id, some_data
    ) VALUES (
      @newId,
      list_item,
    );
END LIST INSERT ???

    COMMIT;
  END ;;
DELIMITER ;

我的想法是通过逗号分隔的字符串传入要插入表 B 的项目列表。值是字符串。我不确定在 LIST INSERT 部分中该做什么。我需要某种循环吗?到目前为止,我有正确的方法来执行此存储过程吗?我不想批量处理,因为列表中可能有数百甚至数千个项目。有更好的解决方案吗?我使用的是直接 JDBC。

【问题讨论】:

    标签: mysql stored-procedures jdbc


    【解决方案1】:

    是的,您需要一个循环,您可以在其中使用 substring_index() 来获取列表中的值。该解决方案基于this SO topic的答案:

    DELIMITER ;;
    CREATE PROCEDURE insert_group_alert(
      IN _some_data_a         VARCHAR(255),
      IN _data_list_b         TEXT,
    )
      BEGIN
        DECLARE strLen    INT DEFAULT 0;
        DECLARE SubStrLen INT DEFAULT 0;
        DECLARE EXIT HANDLER FOR SQLEXCEPTION
        BEGIN
          ROLLBACK;
        END;
        START TRANSACTION;
    
        INSERT INTO TableA (
          some_data,
          counter
        )
        VALUES (
          _some_data_a,
          1
        ) -- you do not really need this, since you do not provide an id
        ON DUPLICATE KEY UPDATE
          counter          = counter + 1;
    
        SELECT last_insert_id()
          INTO @newId;
    
        do_this:
          LOOP
            SET strLen = CHAR_LENGTH(_data_list_b);
    
            INSERT INTO TableB (table_a_id, some_data) VALUES(@newId,SUBSTRING_INDEX(_data_list_b, ',', 1));
    
            SET SubStrLen = CHAR_LENGTH(SUBSTRING_INDEX(_data_list_b, ',', 1))+2;
            SET _data_list_b = MID(_data_list_b, SubStrLen, strLen); --cut the 1st list item out
    
            IF _data_list_b = '' THEN
              LEAVE do_this;
            END IF;
          END LOOP do_this;
    
        COMMIT;
      END ;;
    DELIMITER ;
    

    【讨论】:

      猜你喜欢
      • 2014-03-06
      • 1970-01-01
      • 2017-12-09
      • 1970-01-01
      • 1970-01-01
      • 2020-07-10
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多