You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

在MyBatis中用SELECT调用MySQL存储过程报错,求问题原因

问题分析与解决方案

你的代码存在多处语法和逻辑错误,以下是具体问题和修正方案:

一、存储过程INSERT_DATA的错误

  1. 参数未匹配:存储过程定义的参数是columnName和tableName,但内部拼接SQL时误用了columninfo和tableinfo,完全没用到传入的参数。
  2. 拼接语法错误:concat语句末尾缺少闭合双引号,且from与表名之间无空格,导致生成的SQL本身语法失效。
  3. 标识符无防护:直接拼接表名、列名到SQL中,既容易因关键字/特殊字符引发语法错误,也存在SQL注入风险,需用反引号包裹标识符。

修正后的存储过程:

CREATE PROCEDURE `INSERT_DATA`(IN columnName varchar(40), IN tableName varchar(40))
BEGIN
  SET @s := CONCAT(
    "INSERT INTO DATA_DB SELECT `", columnName, "` FROM `", tableName, "`"
  );
  PREPARE stmt FROM @s;
  EXECUTE stmt;
  DEALLOCATE PREPARE stmt;
END

二、MyBatis XML映射的错误

  1. 属性拼写错误:statementTyle是笔误,正确属性名为statementType。
  2. 调用逻辑错误:不能在SELECT语句中嵌套CALL调用存储过程,这种写法不符合SQL语法规范。你的需求是遍历TEMP表记录调用存储过程,需调整实现方式。

修正后的实现方案

方案1:Java层遍历调用(适合小数据量)

先查询TEMP表所有记录,再逐个调用存储过程:

  • 查询TEMP的MyBatis映射:
<select id="getAllTempRecords" resultType="map">
  SELECT tableinfo, columninfo FROM TEMP
</select>
  • 调用存储过程的MyBatis映射:
<insert id="callInsertDataProc" statementType="CALLABLE">
  {CALL INSERT_DATA(#{columnName}, #{tableName})}
</insert>
  • Java代码逻辑:
List<Map<String, String>> tempRecords = tempMapper.getAllTempRecords();
for (Map<String, String> record : tempRecords) {
  String tableName = record.get("tableinfo");
  String columnName = record.get("columninfo");
  dataMapper.callInsertDataProc(columnName, tableName);
}

方案2:存储过程内部批量处理(适合大数据量)

直接在存储过程中遍历TEMP表,减少数据库交互:

CREATE PROCEDURE `BATCH_INSERT_DATA`()
BEGIN
  DECLARE done INT DEFAULT FALSE;
  DECLARE v_tableName VARCHAR(40);
  DECLARE v_columnName VARCHAR(40);
  DECLARE cur CURSOR FOR SELECT tableinfo, columninfo FROM TEMP;
  DECLARE CONTINUE HANDLER FOR NOT FOUND SET done = TRUE;

  OPEN cur;
  read_loop: LOOP
    FETCH cur INTO v_tableName, v_columnName;
    IF done THEN
      LEAVE read_loop;
    END IF;
    SET @s := CONCAT(
      "INSERT INTO DATA_DB SELECT `", v_columnName, "` FROM `", v_tableName, "`"
    );
    PREPARE stmt FROM @s;
    EXECUTE stmt;
    DEALLOCATE PREPARE stmt;
  END LOOP;
  CLOSE cur;
END

对应的MyBatis映射:

<insert id="callBatchInsertProc" statementType="CALLABLE">
  {CALL BATCH_INSERT_DATA()}
</insert>

内容的提问来源于stack exchange,提问作者Hyung Jin Lee

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.13 22:30:55