Mysql
 sql >> база данни >  >> RDS >> Mysql

Разделете низ и преминете през стойности в MySql процедура

Ще трябва да бъдете малко по-внимателни с манипулацията на низовете. Не можете да използвате REPLACE() за това, защото това ще замени множество събития, повреждайки вашите данни, ако един елемент в списъка, разделен със запетая, е подниз на друг елемент. INSERT() низ функция е по-добре за това, да не се бърка с INSERT израз, използван за вмъкване в таблица.

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 ;

След това таблица за тестване:

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

Новата таблица е празна.

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

Извикайте процедурата.

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

Обърнете внимание, че „засегнат 1 ред“ не означава това, което бихте очаквали. Отнася се за последното вмъкване, което направихме. Тъй като вмъкваме един ред наведнъж, ако процедурата вмъква поне един ред, винаги ще получавате брой редове 1; ако процедурата не вмъкне нищо, ще получите 0 засегнати реда.

Сработи ли?

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



  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. Как да свиете/изчистите ibdata1 файл в MySQL

  2. Вмъкване на първичен ключ за автоматично увеличение в съществуващата таблица

  3. Защо MySQL не поддържа точност от милисекунди/микросекунди?

  4. Разбиране на застой в MySQL и PostgreSQL

  5. SQL - Как да транспонирам?