因某些原因无法工作的SQL存储过程

后端开发 2026-07-12

我正在尝试基于MySQL数据库系统编写一个简单的存储过程,接受一个字符串作为参数。该过程随后将其拆分成更短的字符串(使用分隔符),使每个字符串都是大于0 的数字。否则,如果子字符串根本不是数字,就会被丢弃。结果需要作为单列表返回。不幸的是,由于某些未知原因,我没有得到预期的结果。能否请人看看代码并帮我修复错误?

存储过程和函数(不需要任何数据库表):

CREATE DEFINER=`root`@`localhost` PROCEDURE `new_procedure`(
    IN variants VARCHAR(50)
)
BEGIN
DECLARE counter INT DEFAULT 0;
SET
    @validated_params = FALSE,
    @params_number = (CHAR_LENGTH(variants) - CHAR_LENGTH(REPLACE(variants, ';', '')) + 1
);
SET
    @correct_params = JSON_ARRAY('[3, 1]');
WHILE counter < @params_number DO 
    SET
      counter = counter + 1;
    SET
      @variant = split_string(@variants, ';', counter);
    IF @variant > 0 THEN
        SET
            @correct_params = JSON_ARRAY_APPEND(@correct_params, '$', @variant);
    END IF;
END WHILE;
IF JSON_LENGTH(@correct_params) = @params_number THEN
    SET
      @validated_params = TRUE;
END IF;
SELECT variant_number FROM JSON_TABLE(@correct_params, '$[*]' COLUMNS (variant_number INT PATH '$')) AS variant_number;
END
CREATE DEFINER=`root`@`localhost` FUNCTION `split_string`(
    string_to_split VARCHAR(250),
    delimimiter VARCHAR(5),
    position INT
) RETURNS int
    DETERMINISTIC
BEGIN
SET
    @splitted_string = REPLACE(
        SUBSTRING(
            SUBSTRING_INDEX(string_to_split, delimimiter, position),
            CHAR_LENGTH(SUBSTRING_INDEX(string_to_split, delimimiter, position - 1)) + 1
        ), delimimiter, ''
    );
SET
    @splitted_number = (
        CASE WHEN @splitted_string REGEXP '^[0-9]+$' THEN
            CAST(@splitted_string AS UNSIGNED) ELSE -1 END
        );
RETURN @splitted_number;
END

在用以下示例参数运行存储过程后,我们应该得到一个形如的表:

CALL new_procedure('2, b7, vb, 9');
变体编号
3
1
2
9

然而,我得到的是一个空表……

解决方案

由于你在使用JSON(json_array_append、json_table),你可以使用这些工具,而不需要实现string_split。

CREATE PROCEDURE `new_procedure6`(
    IN variants VARCHAR(50)
)
BEGIN
    with src as(
    SELECT variant_number,
      count(variant_number)over() validated,
      count(*)over()-count(variant_number)over()  not_validated
    FROM JSON_TABLE(concat('["',replace(concat('3,1,',variants),',','","'),'"]')
       , '$[*]' 
        COLUMNS (variant_number INT PATH '$')) AS variant_number
    )
    select * from src
    where variant_number is not null
    ;
END ;

call new_procedure6('1,v7,vb,9');

输出:

+----------------+-----------+---------------+
| variant_number | validated | not_validated |
+----------------+-----------+---------------+
|              3 |         4 |             2 |
|              1 |         4 |             2 |
|              1 |         4 |             2 |
|              9 |         4 |             2 |
+----------------+-----------+---------------+

示例中的分隔符是 ,
Fiddle

Upd1
当问题是 “如何把以分隔符分隔的字符串(值的列表)转换成一个值表”

set @variants="2,v7,vb,9";

SELECT rn,variant_number
FROM JSON_TABLE( concat('["',replace(@variants,',','","'),'"]')
       , '$[*]' 
        COLUMNS (
              rn FOR ORDINALITY,
              variant_number varchar(10) PATH '$'
            )
     ) AS variant_number

输出为

行号 变体编号
1 2
2 v7
3 vb
4 9

例如

SELECT *
FROM myTable t
WHERE t.id IN(
       SELECT id
       FROM JSON_TABLE( concat('["',replace(@idList,',','","'),'"]'), '$[*]' 
               COLUMNS ( id int PATH '$')
           ) AS ids
      )
站内所有文章版权归属LeftHeroAI导航站,无授权禁止任何主体转载、抄袭、复制内容,亦不得私自架设镜像站点。一经侵权,本站将通过法律途径追责。

相关文章