sql >> Databasteknik >  >> RDS >> Mysql

Dela en sträng och gå igenom värden i MySql Procedure

Du måste vara lite mer försiktig med din strängmanipulation. Du kan inte använda REPLACE() för detta, eftersom det kommer att ersätta flera förekomster, vilket skadar din data om ett element i den kommaseparerade listan är en delsträng till ett annat element. INSERT() strängfunktion är bättre för detta, inte att förväxla med INSERT uttalande som används för att infoga i en tabell.

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 ;

Därefter en tabell för testning:

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

Den nya tabellen är tom.

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

Ring proceduren.

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

Observera att "1 rad påverkad" inte betyder vad du kan förvänta dig. Det hänvisar till den senaste infogningen vi gjorde. Eftersom vi infogar en rad i taget, om proceduren infogar minst en rad får du alltid ett antal rader på 1; om proceduren inte infogar något, kommer du att få 0 rader påverkade.

Fungerade det?

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



  1. Fördelar och nackdelar med att implementera en hybrid molnmiljö

  2. Hur får jag lokal data till en skrivskyddad databas med dplyr?

  3. Vad är nytt i MariaDB 10.4

  4. Hur sjukvården använder databaser