Как разделить строку, разделенную запятыми, внутри хранимой процедуры?

#sql #string #firebird #firebird2.5

#sql #строка #firebird #firebird2.5

Вопрос:

Как разделить строку, разделенную запятыми, на строки внутри процедуры хранения и вставить их в поле таблицы?

Использование Firebird 2.5

Ответ №1:

Я публикую измененную версию Майкла, возможно, это будет кому-то полезно.

Изменения заключаются в:

  1. SPLIT_STRING — это выбираемая процедура.
  2. Возможен пользовательский разделитель.
  3. Он анализирует также случаи, когда разделитель является первым символом в 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 ; ^
  

Комментарии:

1. Отличная работа @MartjinPieters 🙂

Ответ №2:

Вот пример того, как разделить строку и записать вложенные строки в таблицу:

 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
  

Комментарии:

1. Просто к сведению: это не вернет никакого результата для AINPUT like ',1,2' , но вернет три подстроки для AINPUT like '1,2,' .

Ответ №3:

Использовать ПОЗИЦИЮ http://www.firebirdsql.org/refdocs/langrefupd21-intfunc-position.html

и

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

функции в инструкции WHILE DO

Комментарии:

1. Добро пожаловать в Stack Overflow! Хотя теоретически это может дать ответ на вопрос, было бы предпочтительнее включить сюда основные части ответа и предоставить ссылку для справки. Спасибо

Ответ №4:

Я использую аналогичное решение, опубликованное некоторое время назад Иржи Цинкурой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 до 32000 возникает исключение «Превышен предел реализации», поэтому будьте осторожны. Я предлагаю вместо этого использовать текст ПОДТИПА BLOB 🙂

Ответ №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'));
  

Комментарии:

1. Вы спасли мне жизнь, большое вам спасибо, я пытался найти что-то подобное, что могло бы работать для Informix.