PAYATHON 2026

MySQL 存储过程如何拆分并筛选正整数?

数据阿明

结论

当前描述的代码有几处相互独立的问题,可能导致结果不符合预期:调用使用逗号分隔,过程却按分号计算和拆分;过程把参数 variants 当作会话变量 @variants 使用;初始化 JSON 数组的方式也与预期结构不符。代码中还有截断和占位符,因此无法还原或确认原过程的完整语法。

输入也与预期结果不一致。CALL new_procedure('2, b7, vb, 9'); 中大于 0 的数字只有 2 和 9,不会产生 3 和 1。如果预期结果是 3、1、2、9,需要提供包含这些数字的实际输入。

主要问题

  1. 分隔符不一致:过程用 ';' 计算片段数量,也用 ';' 调用 split_string,但示例字符串使用逗号分隔。应统一使用逗号,或将调用字符串改为分号分隔。
  2. 参数引用错误:过程参数名是 variants,代码却调用 split_string(@variants, ...)。@variants 是会话变量,不会自动取得过程参数的值。这里应传入 variants。
  3. JSON 初值不是预期的数字数组:JSON_ARRAY('[3, 1]') 创建的是一个包含字符串 "[3, 1]" 的数组,而不是包含数字 3 和 1 的数组。因此,追加和 JSON_TABLE 处理的结构可能与预期不同。
  4. 输入片段数可能与结果数量混淆:@params_number 统计输入片段数,而结果只保留有效数字。用两者比较来判断结果是否有效,不能说明数组内容正确。如果初始数组还包含一个字符串,长度比较也会进一步偏离预期。
  5. 代码片段不完整:JSON_TABLE 的列定义、函数中的正则表达式和过程主体都被占位符或截断内容打断。需要完整 SQL 才能确认这些部分是否还有语法错误。

一种实现方式

如果使用 MySQL 8.0,可以在过程内用递归 CTE 拆分逗号分隔的字符串,再筛选由数字组成且大于 0 的片段:

DELIMITER //

CREATE PROCEDURE new_procedure(IN variants VARCHAR(250))
BEGIN
    WITH RECURSIVE parts AS (
        SELECT
            SUBSTRING_INDEX(variants, ',', 1) AS part,
            CASE
                WHEN LOCATE(',', variants) > 0
                    THEN SUBSTRING(variants, LOCATE(',', variants) + 1)
                ELSE ''
            END AS rest
        UNION ALL
        SELECT
            SUBSTRING_INDEX(rest, ',', 1) AS part,
            CASE
                WHEN LOCATE(',', rest) > 0
                    THEN SUBSTRING(rest, LOCATE(',', rest) + 1)
                ELSE ''
            END AS rest
        FROM parts
        WHERE rest <> ''
    )
    SELECT CAST(TRIM(part) AS UNSIGNED) AS variant_number
    FROM parts
    WHERE TRIM(part) REGEXP '^[0-9]+$'
      AND CAST(TRIM(part) AS UNSIGNED) > 0;
END//

DELIMITER ;

调用:

CALL new_procedure('2, b7, vb, 9');

这个输入会返回一列 variant_number,值为 2 和 9。b7 和 vb 不符合纯数字格式,会被过滤。TRIM 会去掉片段两侧的空格。

注意事项

此示例按逗号拆分字符串,并依赖 MySQL 8.0 的递归 CTE 支持。如果实际需要使用分号,应将代码中的逗号分隔符改为分号。要核对原存储过程本身的具体错误,还需要提供未截断的过程和函数定义,以及能对应预期输出的输入值。

备注:内容仅供参考。