32

正規表現を使用して、カンマ区切りの文字列を MySQL の一時テーブルに解析できますか?

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

8 に答える 8

39

これはCan Mysql Split a column?とほぼ同じ質問です。

MySQL には文字列分割機能がないため、回避策を講じる必要があります。上記の回答ページにリストされている方法のいずれかを使用してデータを分割すると、データに対して何でもできます。

そのカスタム関数をループして、空が返されたときに中断することができます。いくつかの構文を再生して学習する必要があります (少なくとも私はそうする必要があります)。ただし、mysql の FOR ループの構文は次のとおりです: 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 のみを解析し、挿入クエリを一時テーブルに実行できます。しかし、その種の作業に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 $$
于 2012-08-06T20:14:59.043 に答える
4
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 $$
于 2014-08-13T09:42:49.733 に答える
2

テーブルの値がない場合などのために、私はこれを行いました:

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;

最良の答えではないかもしれませんが、関数や手順の助けがなくても機能し、追加のテーブルなどもありません。

于 2016-07-04T16:27:49.870 に答える
1

MySQL では正規表現を使用して複雑な検索のパターンを指定できますが、文字列を解析することはできません。

ただし、REPLACE と CONCATENATE を使用して INSERT クエリを作成し、データを一時テーブルに保存できます。

于 2012-08-06T20:15:34.597 に答える
0

分割しようとしているテキストにマルチバイト文字が含まれている場合、LENGTH が正しく計算されないため、このアプローチは失敗します。このような場合、LENGTH の代わりに CHAR_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

于 2015-12-17T18:02:20.207 に答える