MySQL CSV Row для нескольких строк - PullRequest
3 голосов
/ 18 февраля 2011

Мне нужно перенести старую базу данных в новую. К сожалению, парень, который написал старую базу данных, создал отношение n, n, используя поле с разделенными запятыми внешними ключами.

Я хотел бы написать запрос mysql (возможно, с использованием вставки в ... select), который разбивает эти разделенные запятыми внешние ключи, чтобы я мог построить таблицу, в которой каждая строка является внешним ключом.

Возможно ли это?

Ответы [ 2 ]

2 голосов
/ 18 февраля 2011

Это не просто сделать в чистом SQL.Проще будет по очереди извлекать каждую запись, используя выбранный вами язык программирования, и вставлять записи таблицы соединений «многие ко многим», используя поля, разделенные запятыми.Следующий псевдокод предлагает подход, который вы могли бы использовать:

for each (id, csv_foreign_keys) in source_rows do
    foreign_keys = split ',', csv_foreign_keys

    for each fk in foreign_keys do
        insert (id, fk) into many-to-many link table

После того, как вы сделали это, существующий столбец, содержащий разделенные запятыми внешние ключи, может быть удален.

0 голосов
/ 18 февраля 2011

Мое решение

DELIMITER $$

DROP FUNCTION IF EXISTS SPLITCVS $$
DROP PROCEDURE IF EXISTS MIGRATE $$

CREATE FUNCTION SPLITCVS (
 x VARCHAR(255),
 delim VARCHAR(12),
 pos INT
)
RETURNS VARCHAR(255)
RETURN REPLACE(SUBSTRING(SUBSTRING_INDEX(x, delim, pos),
       LENGTH(SUBSTRING_INDEX(x, delim, pos -1)) + 1),
       delim, '') $$

CREATE PROCEDURE MIGRATE () 
BEGIN
    DECLARE done INT DEFAULT 0;
    DECLARE id INT(11);
    DECLARE csv BLOB;
    DECLARE cur CURSOR FOR SELECT uid,foreigns FROM old;
    DECLARE CONTINUE HANDLER FOR NOT FOUND SET done = 1;

    OPEN cur;

    read_loop: LOOP
        FETCH cur INTO id, csv;
        IF done THEN
          LEAVE read_loop;
        END IF;

        IF LENGTH(csv) <> 0 THEN
            SET @i = 0;
            SET @seps = LENGTH(csv) - LENGTH(REPLACE(csv, ',', ''));

            IF RIGHT(csv,1) <> ',' THEN
                SET @seps = @seps + 1;
            END IF;

            WHILE @i < @seps DO
                SET @i = @i + 1; 
                INSERT INTO db.newtable(uid_local,uid_foreign)
                VALUES (id,SPLITCVS(csv,',',@i));
            END WHILE;
        END IF;
    END LOOP;

    CLOSE cur;
END $$

CALL MIGRATE() $$

DROP FUNCTION SPLITCVS $$
DROP PROCEDURE MIGRATE $$
...