所以我有两张table。路径表的外键“media\u id”与媒体表“id”连接。每个介质可以有多个路径。这一切都很好。
当我尝试用csv导出和导入这些表时,问题就出现了。我可以正常导出它们,但当我要导入它们(第一个媒体表)时,媒体表中的主键“id”被设置为自动递增,并且当媒体表与加载数据填充一起导入时,它将自己生成新的“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条答案
按热度按时间mspsb9vt1#
正如我试图在评论中解释的(可能很糟糕),我认为在这种情况下使用标识符而不是跟踪整数会更好,因为它提供了一个关键的见解,一个简单的数字生成来消除它与它的邻居之间的歧义不会:
它是一种东西,所以它活着。
这个强大的设计模式意味着,当你去导入它时,如果你不使用(希望是已知的)某个旧的导入文件的假设(与未来神奇的导入文件相反),对可能已经在数据集中表示的数据进行整体导入(说真的,可能在我使用重叠的数据集键入时加载了另外两个快照),您只需忽略更新,因为您当前所表示的内容应该比旧数据文件更新,并且其中的内容具有标识:
uuid是uuid是uuid是uuid。。。
这是假设域的数据模型是一致的,而加载的表示仅仅是表示。因此,将先前的外部表示形式与唯一的跨系统标识符序列化,可以在将其从系统中删除,然后重新引入时更容易地处理它。
尤其是在较小的系统中,uuid很容易使用(应该考虑在短时间内生成多个数字并跨域集成),但它们不是必需的,除非您需要这种类型的导出/导入功能,并且希望它在导入时保持其身份。
你不必这样做,请不要把这理解为我在推动重写。然而,如果您在设计时考虑到这一点,请扪心自问,我的数据是否需要放在盒子之外?
hjzp0vay2#
我通常不运行这种类型的操作,因此这可能是伪代码,需要调整,但我认为您可以这样做:
https://stackoverflow.com/a/2710714
然后用php,比如说,拉取这些文件并加载它们:
如果
$table_from_filename
是media_201809041045
,现在您已将其作为temp_media_201809041045
,所以现在,对于五个表,事情可能会变得复杂,例如,您必须保持优先顺序(父表在子表之前),除非有方法在导入每个表之前禁用它。
如果可以将它们作为(temp)表放入数据库,那么现在就可以对它们进行处理,例如查询每个父行,对源表执行insert,然后使用
last_insert_id
,可以为以后的子行创建交换索引。如果外键总是遵循相同的模式,例如。media
以及media_id
,然后就可以很容易地创建一个函数来处理这个问题,只需使用要复制的五个表名中的表名即可。另一件事,在
CREATE
呼叫,您可能要删除TEMPORARY
如果你需要的不仅仅是打个电话,还可以得到一个或一系列的UNION
“d”SELECT
s。您可以在查询中结束,但如果使用临时表,它将在下一个查询中消失。最后,运行DROP TABLE
对于现在的“临时”常规表,只需确保它是实际的临时表。