Mysql
 sql >> Datenbank >  >> RDS >> Mysql

Teilen Sie eine Zeichenfolge und durchlaufen Sie die Werte in der MySql-Prozedur

Sie müssen mit Ihrer Saitenmanipulation etwas vorsichtiger sein. Sie können REPLACE() nicht verwenden weil dadurch mehrere Vorkommen ersetzt werden und Ihre Daten beschädigt werden, wenn ein Element in der durch Kommas getrennten Liste eine Teilzeichenfolge eines anderen Elements ist. Der INSERT() Zeichenfolgenfunktion ist dafür besser, nicht zu verwechseln mit INSERT Anweisung zum Einfügen in eine Tabelle.

DELIMITER $$

DROP PROCEDURE IF EXISTS `insert_csv` $$
CREATE PROCEDURE `insert_csv`(_list MEDIUMTEXT)
BEGIN

DECLARE _next TEXT DEFAULT NULL;
DECLARE _nextlen INT DEFAULT NULL;
DECLARE _value TEXT DEFAULT NULL;

iterator:
LOOP
  -- exit the loop if the list seems empty or was null;
  -- this extra caution is necessary to avoid an endless loop in the proc.
  IF CHAR_LENGTH(TRIM(_list)) = 0 OR _list IS NULL THEN
    LEAVE iterator;
  END IF;
 
  -- capture the next value from the list
  SET _next = SUBSTRING_INDEX(_list,',',1);

  -- save the length of the captured value; we will need to remove this
  -- many characters + 1 from the beginning of the string 
  -- before the next iteration
  SET _nextlen = CHAR_LENGTH(_next);

  -- trim the value of leading and trailing spaces, in case of sloppy CSV strings
  SET _value = TRIM(_next);

  -- insert the extracted value into the target table
  INSERT INTO t1 (c1) VALUES (_value);

  -- rewrite the original string using the `INSERT()` string function,
  -- args are original string, start position, how many characters to remove, 
  -- and what to "insert" in their place (in this case, we "insert"
  -- an empty string, which removes _nextlen + 1 characters)
  SET _list = INSERT(_list,1,_nextlen + 1,'');
END LOOP;

END $$

DELIMITER ;

Als nächstes eine Tabelle zum Testen:

CREATE TABLE `t1` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `c1` varchar(64) NOT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

Die neue Tabelle ist leer.

mysql> SELECT * FROM t1;
Empty set (0.00 sec)

Rufen Sie die Prozedur auf.

mysql> CALL insert_csv('foo,bar,buzz,fizz');
Query OK, 1 row affected (0.00 sec)

Beachten Sie, dass "1 Zeile betroffen" nicht das bedeutet, was Sie erwarten würden. Es bezieht sich auf die letzte Einfügung, die wir gemacht haben. Da wir jeweils eine Zeile einfügen, wenn die Prozedur mindestens einfügt eine Zeile, erhalten Sie immer eine Zeilenanzahl von 1; Wenn die Prozedur nichts einfügt, erhalten Sie 0 betroffene Zeilen.

Hat es funktioniert?

mysql> SELECT * FROM t1;
+----+------+
| id | c1   |
+----+------+
|  1 | foo  |
|  2 | bar  |
|  3 | buzz |
|  4 | fizz |
+----+------+
4 rows in set (0.00 sec)