我正在编写一个脚本,我想在其中将8000多行从一个表传输到另一个具有选定列的数据库中的另一个表。到目前为止,我曾考虑使用PDOStatement::fetchAll()
作为$result
数组来获取整个源表的选定列,然后使用PDO::prepare()
方法准备mySQL插入语句
INSERT INTO targetTable (targetColumn1,targetColumn2...) VALUES
(sourceRow1ForColumn1,sourceRow1ForColumn2,..),
(sourceRow2ForColumn1,sourceRow2ForColumn2,..),
(sourceRow3ForColumn1,sourceRow3ForColumn2,...),...
但我认为这不是一种有效的方法,应该有一种最佳方式来做我想做的事情。有没有更好的方法可以做我想做的事情?
答案 0 :(得分:1)
如果要完成一次,则无需关注性能。
put set_time_limit(0);在PHP文件的开头。
然后,连接到您的第一个数据库。从源表中读取数据并存储在数组中。
现在,断开并连接到新数据库并将数组数据插入目标表
对于照顾重复的密钥,您可以在查询中使用INSERT OR UPDATE ON DUPLICATE。
如果您的记录太大,您可能会遇到内存问题。因此,最好在存储到数组之前获取计数。然后,在循环中和每个循环结束时执行该过程,通过unset()释放数组。因此,您可以拆分记录并以适当的方式保持内存使用。
答案 1 :(得分:1)
执行此操作的最佳方法是使用INSERT ... SELECT语句。
INSERT INTO targetTable (targetColumn1,targetColumn2)
SELECT expr1, expr2 FROM one_table
expr1
和expr2
表示返回您要分别插入targetColumn1
和targetColumn2
列的值的表达式。
表达式可以简单地引用源表中的列名称。
如果表位于同一MySQL实例上的不同数据库(模式)中,则可以使用数据库名称限定表名。 (非限定表名称是指当前数据库中的表(即USE mydatabase。)
如果您当前的数据库是目标数据库,请在FROM子句中限定名称表
INSERT INTO targetTable (targetColumn1,targetColumn2)
SELECT expr1, expr2 FROM anotherdb.one_table
^^^^^^^^^^
如果当前数据库包含源表,则限定targetTable的名称。
或者只是限定两个表名,并不重要的是当前的数据库。
只需在每个表上拥有足够权限的用户连接到MySQL。
GRANT SELECT ON anotherdb.one_table TO myuser@'%';
GRANT INSERT ON targetdb.targetTable TO myuser@'%';
如果插入尝试插入违反targetTable中唯一约束的行,则INSERT ... SELECT与INSERT ... VALUES语句一样会发生同样的事情......语句将失败。
如果您想忽略有关重复项的错误,只是跳过这些行,那么使用INSERT IGNORE ... SELECT atatement。 (IGNORE关键字导致MySQL不跳过该行,而不是在违反唯一键约束时抛出错误。
或者,您可以编写SELECT语句以排除目标表中已存在的行。