LOAD DATA INFILE родительская дочерняя таблица и отношение внешних ключей - PullRequest
0 голосов
/ 08 сентября 2018

Итак, у меня есть 2 таблицы. Таблица путей имеет внешний ключ 'media_id', связанный с таблицей медиа 'id'. Каждый носитель может иметь несколько путей. Это все хорошо работает.

Проблема возникает, когда я пытаюсь экспортировать и импортировать эти таблицы с помощью CSV. Я могу экспортировать их нормально, но когда я иду импортировать их (первую таблицу мультимедиа), первичный ключ 'id' в таблице мультимедиа устанавливается на автоинкремент, а когда таблица мультимедиа импортируется с LOAD DATA INFILE, она генерирует новый 'id' сам по себе, поэтому я потеряю любую связь с таблицей путей.

$sql = "CREATE TABLE $media_table (
            `id` int(11) NOT NULL AUTO_INCREMENT,
            `title` varchar(255) DEFAULT NULL,
            `description` varchar(2000) DEFAULT NULL,
            PRIMARY KEY (`id`),
         ) $charset_collate;";

        $sql = "CREATE TABLE $path_table (
            `id` int(11) NOT NULL AUTO_INCREMENT,
            `path` varchar(500) DEFAULT NULL,
            `def` varchar(50) DEFAULT NULL,
            `media_id` int(11) NOT NULL,
            PRIMARY KEY (`id`),
            INDEX `media_id` (`media_id`),
            CONSTRAINT `mvp_path_ibfk_1` FOREIGN KEY (`media_id`) REFERENCES {$media_table} (`id`) ON DELETE CASCADE ON UPDATE CASCADE
        ) $charset_collate;";

Вот запрос:

$query = "LOAD DATA INFILE '$csv' INTO TABLE {$table}
      FIELDS OPTIONALLY ENCLOSED BY '^'
      TERMINATED BY '|'
      ESCAPED BY ''
      LINES TERMINATED BY '\n'
      IGNORE 1 LINES";

Что-то не так с моим дизайном базы данных и как я могу улучшить это или обойти эту проблему?

Ответы [ 2 ]

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

Поскольку я пытался объяснить (вероятно, плохо) в комментариях, я думаю, что использование идентификатора вместо отслеживания целого числа было бы лучше в этом случае, так как он обеспечивает критическое понимание, то есть простое число, сгенерированное для устранения неоднозначности егоэто не соседи:

Это вещь, поэтому она живет.

Что означает этот мощный шаблон проектирования, так это то, что когда вы собираетесь его импортировать, если выоперируем (предположительно известным) предположением, что используется какой-то старый файл импорта (в отличие от волшебного из будущего), чтобы сделать интегральный импорт над данными, которые уже могут быть представлены в наборе данных (серьезно, могли быть загружены еще два снимка, пока я печатал с перекрывающимися наборами данных), вам просто нужно было бы проигнорировать обновление, так как все, что вы представляли в настоящее время должно быть новее, чем староефайл данных, и вещи в нем имеют идентичность :

UUID - это UUID - этоUUID - это uuid ...

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

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

# Note there's `temp_`, $table_from_filename would be "media".
LOAD DATA INFILE '{$table_from_filename}.csv'
  IGNORE INTO TABLE {$table_from_filename}
  FIELDS OPTIONALLY ENCLOSED BY '"'
  TERMINATED BY '\n'
  ESCAPED BY ''
  LINES TERMINATED BY '\n'

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

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

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

https://stackoverflow.com/a/2710714

CREATE TEMPORARY TABLE
IF NOT EXISTS temp_{$table_name_with_datetime}
AS (SELECT * FROM {$table_name});

# Not sure if this will work, it would need some way
# for the CREATE to be gotten.
SELECT (SHOW CREATE TABLE temp_{$table_name_with_datetime})
  INTO OUTFILE '{$table_name_with_datetime}_create.sql'
  FIELDS TERMINATED BY ''
  OPTIONALLY ENCLOSED BY ''
  LINES TERMINATED BY '\n'
  FROM temp_{$table_name_with_datetime};

SELECT * INTO OUTFILE '{$table_name_with_datetime}.csv'
  FIELDS TERMINATED BY ','
  OPTIONALLY ENCLOSED BY '"'
  LINES TERMINATED BY '\n'
  FROM temp_{$table_name_with_datetime};

Затем с помощью PHP, скажем, вы извлекаете эти файлы и загружаете их:

// This creates the table.
$dbo->query(file_get_contents("{$table_from_filename}_create.sql"));
$dbo->query("
LOAD DATA INFILE '{$table_from_filename}.csv'
  INTO TABLE temp_{$table_from_filename}
  FIELDS OPTIONALLY ENCLOSED BY '"'
  TERMINATED BY '\n'
  ESCAPED BY ''
  LINES TERMINATED BY '\n'
");

Если $table_from_filename было media_201809041045, теперь вы импортировали его как temp_media_201809041045, поэтому

$tablename = "temp_$table_from_filename";

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

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

Еще одна вещь, при вызове CREATE вы можете удалить TEMPORARY из вызова и сохранить стол, если вам нужно больше, чем позвонить и получить один или серию UNION 'd * 1026. * s. Вы можете закончить запрос, но с временной таблицей, он исчезает при следующем запросе. Затем, в конце, запустите DROP TABLE для «временной» обычной таблицы, просто убедитесь, что она является временной.

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