所以我有2张桌子。路径表具有与媒体表“ id”连接的外键“ media_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";
我的数据库设计有问题吗?我该如何改善它或解决这个问题?
答案 0 :(得分:1)
我通常不运行这种类型的操作,因此这可能是伪代码,需要进行调整,但是我认为您可以这样做:
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
呼叫中,如果您需要的不仅仅是呼叫并获得一个或一系列{{1 }}个TEMPORARY
。您可以以查询结尾,但是有了一个临时表,下一个查询就消失了。然后最后,为现在的“临时”常规表运行UNION
,只需确保它是实际的临时表即可。
答案 1 :(得分:0)
当我试图在评论中解释(可能很差)时,我认为在这种情况下使用标识符而不是跟踪整数会更好,因为它提供了关键的见解,即生成一个简单的数字即可消除歧义它的邻居没有:
这是一件事,所以它活了。
这种强大的设计模式的意思是,当您导入它时,如果您正在(希望知道)假设正在使用某些旧的导入文件(而不是将来使用的神奇文件), ,要对可能已经在数据集中表示的数据进行整体导入 (严重的是,当我使用重叠的数据集键入内容时,可能还加载了另外两个快照),您只需忽略更新,因为您现在代表的 应该比那个旧的数据文件新,所以并且其中的事物具有标识:
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'
您不必这样做,请不要在我提倡重写的同时对它进行解释。但是,如果您在设计时考虑了一下,请问问自己,我的数据是否需要保存在包装盒内??