Подтвердить что ты не робот

Разделительная строка с разделителями разделов MySQL в таблицу Temp

Можете ли вы разделить строку, разделенную запятой, на временную таблицу в MySQL с помощью RegEx?

'1|2|5|6' into temp table with 4 rows.
4b9b3361

Ответ 1

Это почти такой же вопрос, как Может ли Mysql разделить столбец?

MySQL не имеет функции разделения строк, поэтому вам нужно выполнять работу. Вы можете делать что-либо с данными после их разделения, используя один из методов, перечисленных на странице ответов выше.

Вы можете запрограммировать эту пользовательскую функцию и сломаться, когда она вернется пустым, вам придется играть и изучать некоторый синтаксис (или, по крайней мере, я бы), но синтаксис цикла FOR в mysql приведен здесь: http://www.roseindia.net/sql/mysql-example/for.shtml

Вы можете выполнить итерацию по нему, увеличивая положение в следующей функции:

CREATE FUNCTION SPLIT_STR(
  x VARCHAR(255),
  delim VARCHAR(12),
  pos INT
)
RETURNS VARCHAR(255)
RETURN REPLACE(SUBSTRING(SUBSTRING_INDEX(x, delim, pos),
       LENGTH(SUBSTRING_INDEX(x, delim, pos -1)) + 1),
       delim, '');

(Кредит: https://blog.fedecarg.com/2009/02/22/mysql-split-string-function/)

Который должен возвращать '', если совпадение не найдено, поэтому разделите цикл, если совпадение не найдено. Это позволит вам только с помощью mysql разбора по разделительной строке и запускать запросы вставки в таблицу temp. Но почему человек не просто использует язык сценариев, например php для такого рода работ?: (

Синтаксис кода для цикла:

DELIMITER $$  

CREATE PROCEDURE ABC(fullstr)

   BEGIN
      DECLARE a INT Default 0 ;
      DECLARE str VARCHAR(255);
      simple_loop: LOOP
         SET a=a+1;
         SET str=SPLIT_STR(fullstr,"|",a);
         IF str='' THEN
            LEAVE simple_loop;
         END IF;
         #Do Inserts into temp table here with str going into the row
         insert into my_temp_table values (str);
   END LOOP simple_loop;
END $$

Ответ 2

Вы можете использовать регулярное выражение в MySQL для указания шаблона для сложного поиска, вы не можете разобрать строки.

Но вы можете создать запрос INSERT с помощью REPLACE и CONCATENATE, чтобы сохранить данные в таблице temp.

Ответ 3

DELIMITER $$  

CREATE PROCEDURE SPLIT_VALUE_STRING()

    BEGIN

        SET @String      = '1,22,333,444,5555,66666,777777';
        SET @Occurrences = LENGTH(@String) - LENGTH(REPLACE(@String, ',', ''));
        myloop: WHILE (@Occurrences > 0)
        DO 
            SET @myValue = SUBSTRING_INDEX(@String, ',', 1);
            IF (@myValue != '') THEN
            /* my code... */
            ELSE
                LEAVE myloop; 
            END IF;
            SET @Occurrences = LENGTH(@String) - LENGTH(REPLACE(@String, ',', ''));
            IF (@occurrences = 0) THEN 
                LEAVE myloop; 
            END IF;
            SET @String = SUBSTRING(@String,LENGTH(SUBSTRING_INDEX(@String, ',', 1))+2);
        END WHILE;                  

   END $$

Ответ 4

Я сделал это, потому что, когда у вас нет табличных значений и т.д.:

select *
from(
    select c, SUBSTRING_INDEX(SUBSTRING_INDEX('1|2|5|6', '|', c+1), '|', -1) as name
    from(
        SELECT (TWO_1.SeqValue + TWO_2.SeqValue + TWO_4.SeqValue + TWO_8.SeqValue + TWO_16.SeqValue + TWO_32.SeqValue) c
        FROM (
            SELECT 0 SeqValue UNION ALL SELECT 1 SeqValue) TWO_1
            CROSS JOIN (SELECT 0 SeqValue UNION ALL SELECT 2 SeqValue) TWO_2
            CROSS JOIN (SELECT 0 SeqValue UNION ALL SELECT 4 SeqValue) TWO_4
            CROSS JOIN (SELECT 0 SeqValue UNION ALL SELECT 8 SeqValue) TWO_8
            CROSS JOIN (SELECT 0 SeqValue UNION ALL SELECT 16 SeqValue) TWO_16 
            CROSS JOIN (SELECT 0 SeqValue UNION ALL SELECT 32 SeqValue) TWO_32
    ) as b
    WHERE c <= (CHAR_LENGTH('1|2|5|6') - CHAR_LENGTH(REPLACE('1|2|5|6', '|', '')))
) as a;

Не может быть лучшим ответом, но работает без помощи функций и процедур, без дополнительных таблиц и т.д.

Ответ 5

Если текст, который вы пытаетесь разбить, содержит mutli-байтовые символы, этот подход будет разбит из-за того, что LENGTH вычисляется неправильно. Для таких случаев следующая версия с CHAR_LENGTH вместо LENGTH работает:

CREATE DEFINER=`root`@`localhost` FUNCTION `strSplit`(
           `src` MEDIUMTEXT CHARACTER SET utf8, 
           `delim` VARCHAR(12), 
           `pos` INTEGER
          )
    RETURNS mediumtext
    LANGUAGE SQL
    NOT DETERMINISTIC
    CONTAINS SQL
    SQL SECURITY DEFINER
    COMMENT ''
BEGIN
  DECLARE output MEDIUMTEXT CHARACTER SET utf8;
  SET output = REPLACE(SUBSTRING(SUBSTRING_INDEX(src, delim, pos) ,  
              CHAR_LENGTH(SUBSTRING_INDEX(src, delim, pos - 1)) + 1) , delim , '');
  IF output = '' THEN SET output = null; END IF;
  RETURN output;
END

Ссылка: http://www.shakedos.com/2011/Nov/23/mysql-split-string-function-fix-split_str.html

Ответ 6

select distinct
  SUBSTRING_INDEX(SUBSTRING_INDEX('1,2,3,4', ',', numbers.n), ',', -1) name
from
  (select @rownum := @rownum + 1 as n
from YourTable
cross join (select @rownum := 0) r
) numbers 
order by
   n

Ответ 7

Просто потому, что мне очень нравится воскрешать старые вопросы:

CREATE PROCEDURE `SPLIT_LIST_STR`(IN `INISTR` TEXT CHARSET utf8mb4, IN `ENDSTR` TEXT CHARSET utf8mb4, IN `INPUTSTR` TEXT CHARSET utf8mb4, IN `SEPARATR` TEXT CHARSET utf8mb4)
BEGIN
    SET @I = 1;
    SET @SEP = SEPARATR;
    SET @INI = INISTR;
    SET @END = ENDSTR;
    SET @VARSTR = REPLACE(REPLACE(INPUTSTR, @INI, ''), @END, '');
    SET @N = FORMAT((LENGTH(@VARSTR)-LENGTH(REPLACE(@VARSTR, @SEP, '')))/LENGTH(@SEP), 0)+1;

    CREATE TEMPORARY TABLE IF NOT EXISTS temp_table(P1 TEXT NULL);

    label1: LOOP
        SET @TEMP = SUBSTRING_INDEX(@VARSTR, @SEP, 1);
        insert into temp_table (`P1`) SELECT @TEMP;
        SET @I = @I + 1;
        SET @VARSTR = REPLACE(@VARSTR, CONCAT(@TEMP, @SEP), '');
        IF @N >= @I THEN
          ITERATE label1;
        END IF;
        LEAVE label1;
      END LOOP label1;
    SELECT * FROM temp_table;
    END

Что дает:

P1
1
2
3
4

При использовании CALL SPLIT_LIST_STR('("', '")', '("1", "2", "3", "4")', '", "');

Я мог бы всплыть позже, чтобы немного пополнить код! Ура!