sql >> Database teknologi >  >> RDS >> Mysql

Opdel en streng og gå gennem værdier i MySql Procedure

Du skal være lidt mere forsigtig med din strengmanipulation. Du kan ikke bruge REPLACE() for dette, fordi det vil erstatte flere forekomster, og ødelægge dine data, hvis et element i den kommaseparerede liste er en understreng af et andet element. INSERT() strengfunktion er bedre til dette, ikke at forveksle med INSERT sætning, der bruges til at indsætte i en tabel.

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 ;

Dernæst en tabel til test:

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

Den nye tabel er tom.

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

Kald proceduren.

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

Bemærk, at "1 række påvirket" ikke betyder, hvad du ville forvente. Det henviser til det sidste indlæg, vi lavede. Da vi indsætter en række ad gangen, hvis proceduren indsætter mindst en række, vil du altid få et rækkeantal på 1; hvis proceduren ikke indsætter noget, vil du få 0 rækker påvirket.

Virkede det?

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



  1. hvordan vælger man lige poster fra en tabel i oracle?

  2. Sådan opretter du forbindelse til Oracle ved hjælp af Service Name i stedet for SID

  3. De bedste SQL Server Performance-fora til hjælp til de sværeste spørgsmål

  4. Tilføjelse af dict-objekt til postgresql