Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/mysql/66.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
MySQL将逗号分隔的字符串拆分为临时表_Mysql_Regex - Fatal编程技术网

MySQL将逗号分隔的字符串拆分为临时表

MySQL将逗号分隔的字符串拆分为临时表,mysql,regex,Mysql,Regex,您可以使用正则表达式将逗号分隔的字符串解析到MySQL中的临时表中吗 '1|2|5|6' into temp table with 4 rows. 这和我的问题差不多 MySQL没有拆分字符串函数,所以您必须进行变通。使用上面答案页面中列出的方法之一拆分数据后,您可以对数据执行任何操作 您可以循环该自定义函数并在其返回空时中断,您必须播放并学习一些语法,或者至少我会,但mysql中for循环的语法如下: 您可以对其进行迭代,增加以下函数中的位置: CREATE FUNCTION SPLIT_

您可以使用正则表达式将逗号分隔的字符串解析到MySQL中的临时表中吗

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

这和我的问题差不多

MySQL没有拆分字符串函数,所以您必须进行变通。使用上面答案页面中列出的方法之一拆分数据后,您可以对数据执行任何操作

您可以循环该自定义函数并在其返回空时中断,您必须播放并学习一些语法,或者至少我会,但mysql中for循环的语法如下:

您可以对其进行迭代,增加以下函数中的位置:

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, '');
学分:

如果没有找到匹配项,则返回,因此如果没有找到匹配项,则中断循环。这将允许您仅使用mysql解析拆分字符串,并在临时表中运行insert查询。但是为什么不使用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 $$

您可以在MySQL中使用正则表达式为复杂搜索指定模式,但不能解析字符串


但是,您可以在REPLACE和CONCATENATE的帮助下构建INSERT查询,以将数据保存到临时表。

如果您尝试拆分的文本包含多字节字符,这种方法将因长度计算不正确而崩溃。对于这种情况,以下使用CHAR_LENGTH而不是LENGTH的版本有效:

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 $$
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

参考资料:

我已经这样做了,当您没有表值时,诸如此类:

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;

可能不是最好的答案,但在没有函数和过程的帮助下,没有额外的表格等,就可以工作。

因为我真的很喜欢重现旧问题:

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
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
当使用调用拆分列表时,'''1,2,3,4'',''


我可能会在稍后弹出来调整代码!干杯

我找到了很好的解决办法

多亏了彼得·布劳利

诀窍:将csv字符串上的分组结果按摩为 插入…值。。。字符串:

另外,若您只想将某个表连接到id列表,则可以使用LIKE运算符。 在我的解决方案中,我从博客帖子URL获取id列表,将它们转换为逗号分隔的列表,开始和结束时使用逗号,然后使用LIKE运算符通过id列表连接相关产品

SELECT b2.id blog_id, b2.id_list, p.id
FROM (
    SELECT b.id,b.text,
    CONCAT(
        ",",
            REPLACE(
                EXTRACTVALUE(b.text,'//a/@id')
                , " ", ","
            )
        ,","
    ) AS id_list
    FROM blog b
) b2
LEFT JOIN production p ON b2.id_list LIKE CONCAT('%,',p.id,',%')
HAVING b2.id_list != ''

这似乎不需要正则表达式来完成。我经常使用MySQL,只是看看我的其他答案,但我永远不会在SQL中这样做。任何脚本语言都更适合此任务。对作业使用正确的工具。这将获取一个值,而不是临时表中的整个列表。是否希望列表中的每个项目都有一行?是的,这样我就可以利用indexingFunction SPLIT_STR fails(索引函数SPLIT_STR失败)处理多个字节的字符大小。使用CHAR_LENGTH而不是LENGTH逗号分隔的字符串来自存储过程,因此我首先需要拆分它。
SELECT b2.id blog_id, b2.id_list, p.id
FROM (
    SELECT b.id,b.text,
    CONCAT(
        ",",
            REPLACE(
                EXTRACTVALUE(b.text,'//a/@id')
                , " ", ","
            )
        ,","
    ) AS id_list
    FROM blog b
) b2
LEFT JOIN production p ON b2.id_list LIKE CONCAT('%,',p.id,',%')
HAVING b2.id_list != ''