如何在存储过程中拆分逗号分隔的字符串?

Posted

技术标签:

【中文标题】如何在存储过程中拆分逗号分隔的字符串?【英文标题】:How to split comma separated string inside stored procedure? 【发布时间】:2011-12-24 18:49:54 【问题描述】:

如何将逗号分隔的字符串拆分为存储过程中的字符串并将它们插入到表字段中?

使用火鸟 2.5

【问题讨论】:

【参考方案1】:

这里是如何拆分字符串并将子字符串写入表格的示例:

create procedure SPLIT_STRING (
  AINPUT varchar(8192))
as
declare variable LASTPOS integer;
declare variable NEXTPOS integer;
declare variable TEMPSTR varchar(8192);
begin
  AINPUT = :AINPUT || ',';
  LASTPOS = 1;
  NEXTPOS = position(',', :AINPUT, LASTPOS);
  while (:NEXTPOS > 1) do
  begin
    TEMPSTR = substring(:AINPUT from :LASTPOS for :NEXTPOS - :LASTPOS);
    insert into new_table("VALUE") values(:TEMPSTR);
    LASTPOS = :NEXTPOS + 1;
    NEXTPOS = position(',', :AINPUT, LASTPOS);
  end
  suspend;
end

【讨论】:

请注意:它不会为AINPUT 返回任何结果,例如',1,2',但它会为AINPUT 返回三个子字符串,例如'1,2,'【参考方案2】:

我正在发布修改后的迈克尔的版本,也许它会对某人有用。

变化是:

    SPLIT_STRING 是一个可选择的过程。 可以自定义分隔符。 它还解析分隔符是 P_STRING 中的第一个字符的情况。
set term ^ ;
create procedure split_string (
    p_string varchar(32000),
    p_splitter char(1) ) 
returns (
    part varchar(32000)
) 
as
  declare variable lastpos integer;
  declare variable nextpos integer;
begin
    p_string = :p_string || :p_splitter;
    lastpos = 1;
    nextpos = position(:p_splitter, :p_string, lastpos);
    if (lastpos = nextpos) then
        begin
            part = substring(:p_string from :lastpos for :nextpos - :lastpos);
            suspend;
            lastpos = :nextpos + 1;
            nextpos = position(:p_splitter, :p_string, lastpos);
        end
    while (:nextpos > 1) do
        begin
            part = substring(:p_string from :lastpos for :nextpos - :lastpos);
            lastpos = :nextpos + 1;
            nextpos = position(:p_splitter, :p_string, lastpos);
            suspend;
        end
end^
set term ; ^

【讨论】:

干得好@MartjinPieters :)【参考方案3】:

使用 位置 http://www.firebirdsql.org/refdocs/langrefupd21-intfunc-position.html

暂停 http://www.firebirdsql.org/refdocs/langrefupd21-intfunc-substring.html

WHILE DO 语句中的函数

【讨论】:

欢迎来到 Stack Overflow!虽然这在理论上可以回答这个问题,it would be preferable 在此处包含答案的基本部分,并提供链接以供参考。谢谢【参考方案4】:

我使用的类似解决方案,不久前由 Jiri Cincura 发布 http://blog.cincura.net/232347-tokenize-string-in-sql-firebird-syntax/

recreate procedure Tokenize(input varchar(1024), token char(1))
returns (result varchar(255))
as
declare newpos int;
declare oldpos int;
begin
  oldpos = 1;
  newpos = 1;
  while (1 = 1) do
  begin
    newpos = position(token, input, oldpos);
    if (newpos > 0) then
    begin
      result = substring(input from oldpos for newpos - oldpos);
      suspend;
      oldpos = newpos + 1;
    end
    else if (oldpos - 1 < char_length(input)) then
    begin
      result = substring(input from oldpos);
      suspend;
      break;
    end
    else
    begin
      break;
    end
  end
end

【讨论】:

【参考方案5】:

它看起来不错,除了一件事,在我的 Firebird 服务器 Varchar 大小声明为 32000 导致“超出实施限制”异常,所以要小心。我建议改用 BLOB SUB_TYPE TEXT :)

【讨论】:

【参考方案6】:

这适用于 Informix 数据库:

DROP FUNCTION rrhh:fnc_StringList_To_Table;
CREATE FUNCTION rrhh:fnc_StringList_To_Table (pStringList varchar(250))
    RETURNING INT as NUMERO;

    /* A esta Funcion le podes pasar una cadena CSV con una lista de numeros
     *      Ejem:  EXECUTE FUNCTION fnc_StringList_To_Table('1,2,3,4');
     * y te devolvera una Tabla con dichos numeros separados uno x fila
     * Autor:  Jhollman Chacon @Cutcsa - 2019 */

    DEFINE _STRING VARCHAR(255);
    DEFINE _LEN INT;
    DEFINE _POS INT;
    DEFINE _START INT;
    DEFINE _CHAR VARCHAR(1);
    DEFINE _VAL INT;

    LET _STRING = REPLACE(pStringList, ' ', '');
    LET _START = 0;
    LET _POS = 0;
    LET _LEN = LENGTH(_STRING);

    FOR _POS = _START TO _LEN
        LET _CHAR = SUBSTRING(pStringList FROM _POS FOR 1);

        IF _CHAR <> ',' THEN 
            LET _VAL = _CHAR::INT;
        ELSE 
            LET _VAL = NULL;
        END IF;

        IF _VAL IS NOT NULL THEN 
            RETURN _VAL WITH RESUME;
        END IF;

    END FOR;

END FUNCTION;

EXECUTE FUNCTION fnc_StringList_To_Table('1,2,3,4');
SELECT * FROM TABLE (fnc_StringList_To_Table('1,2,3,4'));

【讨论】:

以上是关于如何在存储过程中拆分逗号分隔的字符串?的主要内容,如果未能解决你的问题,请参考以下文章

拆分逗号分隔参数传递给SQL Server 2008 R2中的存储过程

拆分用逗号分隔的字符串并将值存储到 int 数组中

oracle中PLSQL存储过程中如何使用逗号分隔的集合(逗号分隔字符串转换为一个集合)

如何传递逗号分隔的输入参数以从另一个存储过程调用存储过程

如何在数字字段的条件下将逗号分隔的数字字符串传递给存储过程?

SQL拆分逗号分隔的字符串