Загрузить CSV в несколько таблиц, решая ключевые проблемы ограничений - PullRequest
0 голосов
/ 05 сентября 2018

В MySQL возможно ли загрузить CSV в хранимую процедуру, которая, в свою очередь, будет заполнять несколько таблиц, каждая из которых имеет зависимости внешнего ключа Exl - первичный ключ table1, который будет использоваться в table2, и первичный ключ table2, который будет используется в table3?

Пример - Один файл с 5 столбцами для чтения в хранимой процедуре, Для каждой строки / записи в CSV-файле используйте column1 и column2 для вставки в table1, получения первичного ключа, а затем вставьте столбец 3 и column4 в таблице 2, получите первичный ключ и используйте первичный ключ table1 и первичный ключ table2 и coulmn5 быть вставленным в table3

Я рассматриваю следующие варианты -

  1. Иметь внешнее приложение, которое читает CSV и передает данные [каждая строка в CSV] в хранимую процедуру с инструкциями подготовки, которые будут принимать заботиться о последующих вставках в необходимые таблицы.
  2. Загрузить CSV во временную таблицу, и иметь хранимую процедуру с подготовкой заявления, которые будут заботиться о последующих вставках в необходимые таблицы.
  3. Иметь внешнее приложение, которое читает CSV, и иметь набор подготовленных заявлений для вставки в последующие столы. Однако получение первичного ключа извне, а затем повторное использование приведет к задержкам ..

Перефразировал вопрос, чтобы узнать эффективный подход к решению этой проблемы, и, если есть возможность загрузить CSV, как мы это сделаем?

Ответы [ 4 ]

0 голосов
/ 17 сентября 2018

После нескольких подходов, как указано выше, найден оптимальный путь. Разделите общие задачи на две основные части - Разделение данных, Загрузка таблиц

  • Разделить - Внешнее приложение для разделения исходного файла на несколько CSV [в соответствии со схемой table1, table2 и table3]
  • Load - Используйте LOAD DATA INFILE , который является самым быстрым способом заполнения таблиц.

[Для всех этих таблиц жестко закодировать первичный ключ вместо зависимости от AUTO_INCREMENT]

Спасибо всем за ваш вклад, предложения и указания.

0 голосов
/ 05 сентября 2018

Нет, см. Приложение C1 - Ограничения для хранимых программ , которое сообщает, что LOAD DATA не может использоваться в хранимой подпрограмме.

Операторы SQL не разрешены в хранимых подпрограммах

Хранимые подпрограммы не могут содержать произвольные операторы SQL. Следующие заявления не допускаются:

Операторы блокировки LOCK TABLES и UNLOCK TABLES.

ALTER VIEW.

НАГРУЗКА ДАННЫХ И ЗАГРУЗКА ТАБЛИЦА.

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

Как правило, операторы, не разрешенные в подготовленных SQL-операторах, также не допускается в хранимых программах.

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

0 голосов
/ 14 сентября 2018

Есть решение. Вы можете использовать некоторые вспомогательные триггеры. Предположим, что вы вставляете данные (или загружаете из файла) в таблицу main . Тогда у вас есть table1 (c1, c2) , table2 (c3, c4) и table3 (c5) , как в вашем вопросе.

Сейчас:

  1. мы используем trigger1 на основной таблице для вставки данных в table1 . Некоторые переменные сеанса используются для хранения временных значений полей.
  2. мы используем триггер2 в таблица1 таблица для вставки данных в таблица2
  3. мы используем триггер3 на таблица2 таблица для вставки данных в таблица3

Давайте посмотрим на скрипт:

CREATE TABLE main (
  c1 varchar(255) DEFAULT NULL,
  c2 varchar(255) DEFAULT NULL,
  c3 varchar(255) DEFAULT NULL,
  c4 varchar(255) DEFAULT NULL,
  c5 varchar(255) DEFAULT NULL
)
ENGINE = INNODB;

CREATE TABLE table1 (
  id int(11) NOT NULL AUTO_INCREMENT,
  c1 varchar(255) DEFAULT NULL,
  c2 varchar(255) DEFAULT NULL,
  PRIMARY KEY (id)
)
ENGINE = INNODB,
AUTO_INCREMENT = 10;

CREATE TABLE table2 (
  id int(11) NOT NULL AUTO_INCREMENT,
  id_ref_table1 int(11) DEFAULT NULL,
  c3 varchar(255) DEFAULT NULL,
  c4 varchar(255) DEFAULT NULL,
  PRIMARY KEY (id)
)
ENGINE = INNODB
AUTO_INCREMENT = 20;

CREATE TABLE table3 (
  id int(11) NOT NULL AUTO_INCREMENT,
  id_ref_table2 int(11) DEFAULT NULL,
  c5 varchar(255) DEFAULT NULL,
  PRIMARY KEY (id)
)
ENGINE = INNODB;

CREATE TABLE main (
  c1 varchar(255) DEFAULT NULL,
  c2 varchar(255) DEFAULT NULL,
  c3 varchar(255) DEFAULT NULL,
  c4 varchar(255) DEFAULT NULL,
  c5 varchar(255) DEFAULT NULL
)
ENGINE = INNODB,
AUTO_INCREMENT = 30;

DELIMITER $$

CREATE TRIGGER trigger1
AFTER INSERT
ON main
FOR EACH ROW
BEGIN
  SET @c3 = NEW.c3;
  SET @c4 = NEW.c4;
  SET @c5 = NEW.c5;

  INSERT INTO table1 (c1, c2)
    VALUES (NEW.c1, NEW.c2);
END
$$

CREATE TRIGGER trigger2
AFTER INSERT
ON table1
FOR EACH ROW
BEGIN
  INSERT INTO table2 (id_ref_table1, c3, c4)
    VALUES (NEW.id, @c3, @c4);
END
$$

CREATE TRIGGER trigger3
AFTER INSERT
ON table2
FOR EACH ROW
BEGIN
  INSERT INTO table3 (id_ref_table2, c5)
    VALUES (NEW.id, @c5);
END
$$

DELIMITER ;

И некоторые операторы INSERT с результатом:

INSERT INTO main(c1, c2, c3, c4, c5) VALUES
('1', '2', '3', '4', '5'),
('11', '22', '33', '44', '55');


SELECT id, c1, c2 FROM table1;
------------------------------
10  1   2
11  11  22

SELECT id, id_ref_table1, c3, c4 FROM table2;
---------------------------------------------
20  10  3   4
21  11  33  44

SELECT id, id_ref_table2, c5 FROM table3;
-----------------------------------------
30  20  5
31  21  55
0 голосов
/ 05 сентября 2018

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

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

Надеюсь, что это даст вам ключ к началу работы.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...