sql >> Database >  >> RDS >> Mysql

Splits een string en loop door waarden in MySql Procedure

Je moet wat voorzichtiger zijn met je stringmanipulatie. U kunt REPLACE() niet gebruiken hiervoor, omdat dat meerdere keren voorkomt, waardoor uw gegevens worden beschadigd als een element in de door komma's gescheiden lijst een substring is van een ander element. De INSERT() tekenreeksfunctie is hiervoor beter, niet te verwarren met de INSERT statement gebruikt om in een tabel in te voegen.

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 ;

Vervolgens een tabel om te testen:

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

De nieuwe tafel is leeg.

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

Bel de procedure.

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

Merk op dat de "1 rij getroffen" niet betekent wat u zou verwachten. Het verwijst naar de laatste invoeging die we deden. Aangezien we één rij tegelijk invoegen, als de procedure minstens . invoegt één rij, je krijgt altijd een rijtelling van 1; als de procedure niets invoegt, worden 0 rijen beïnvloed.

Is het gelukt?

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



  1. Op PostgreSQL gebaseerde applicatieprestaties:latentie en verborgen vertragingen

  2. Hoe retourneer ik gehele en numerieke kolommen uit MySQL als gehele getallen en cijfers in PHP?

  3. Problemen met PostgreSQL-prestaties identificeren met trage query's

  4. SQL Server Databasenaam wijzigen