【问题标题】:mySQL transfer 8000+ rows from one table to another PHPmySQL 将 8000+ 行从一个表传输到另一个 PHP
【发布时间】:2016-08-23 18:44:39
【问题描述】:

我正在编写一个脚本,我希望将 8000 多行从一个表传输到另一个数据库中的另一个表,其中包含选定的列。到目前为止,我曾想过使用PDOStatement::fetchAll() 作为$result 数组来获取整个源表的选定列,然后使用PDO::prepare() 方法准备一个mySQL 插入语句作为

INSERT INTO targetTable (targetColumn1,targetColumn2...) VALUES 
(sourceRow1ForColumn1,sourceRow1ForColumn2,..),
(sourceRow2ForColumn1,sourceRow2ForColumn2,..),
(sourceRow3ForColumn1,sourceRow3ForColumn2,...),...

但我认为这不是一种有效的方式,应该有一种最佳方式来做我想做的事。有没有更好的方法可以做我想做的事?

【问题讨论】:

  • 使用cli导出到.sql文件,替换表名和列名,导入sql?
  • 我真的不希望这个过程是手动的,因为非技术人员会使用我正在做的事情。
  • insert into targetTable select * from sourceTable ?
  • 8000 条记录是微不足道的。 fetchAll() 来自源表,循环数据,一次插入一个到目标表。时间不应超过 30 秒。如果您尝试使用显示的多插入查询,那么它很容易出错并超出长度限制。
  • 我认为这是一个更糟糕的主意。 @MonkeyZeus

标签: php mysql insert


【解决方案1】:

执行此操作的最佳方法是使用 INSERT ... SELECT 语句。

INSERT INTO targetTable (targetColumn1,targetColumn2)
SELECT expr1, expr2 FROM one_table

expr1expr2 表示返回要分别插入到 targetColumn1targetColumn2 列中的值的表达式。

表达式可以是对源表中列名的简单引用。


如果表位于同一 MySQL 实例上的不同数据库(模式)中,您可以使用数据库名称来限定表名。 (不合格的表名是指当前数据库中的一个表(即USE mydatabase)。

如果您当前的数据库是目标数据库,请在 FROM 子句中限定名称表

INSERT INTO targetTable (targetColumn1,targetColumn2)
SELECT expr1, expr2 FROM anotherdb.one_table
                         ^^^^^^^^^^

如果当前数据库包含源表,则限定目标表的名称。

或者只是限定两个表名,而当前是什么数据库并不重要。


只需以对每个表具有足够权限的用户身份连接到 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 语句来排除目标表中已存在的行。

【讨论】:

  • 对不起,我忘了提到目标表在不同的数据库中。让我编辑我的问题
  • 同一个 MySQL 实例上的不同数据库,还是不同 MySQL 实例上的?
  • 两个数据库在同一台服务器上。源在database1.source,目标是database2.target
  • @ZohaibAslam 如果另一个数据库模式在同一台机器上(相同的 mysql 实例),也只需说明数据库名称。 insert into db1.tableA (col1,col2) select col3, col4 from db2.tableB
  • 我不知道用户权限是否确实按照您的建议发挥了作用。我的意思是对于 db1 我必须将 user1 放在连接字符串及其凭据中,但对于 db2 有一个 user2
【解决方案2】:

如果只做一次,就不需要关心性能了。

把 set_time_limit(0);在 PHP 文件的开头。

然后,连接到您的第一个数据库。从源表中读取数据并存储在数组中。

现在,断开连接并连接到新数据库,并将数组数据插入目标表

为了关心重复键,您可以在查询中使用 INSERT OR UPDATE ON DUPLICATE。

如果您的记录会很大,您可能会遇到内存问题。因此,最好在存储到数组之前获取计数。然后,在循环中执行该过程,并在每个循环结束时,通过 unset() 释放数组。因此,您拆分记录并以适当的方式保持内存使用。

【讨论】:

  • 对不起,我忘了提到目标表在不同的数据库中。让我编辑我的问题。
  • @ZohaibAslam,所以,我改变了答案
  • 谢谢,插入频率几乎是每天 5 次。另外我想知道如何处理源表中重复的键值。
  • 你每次都是手动做的吗?还是有预定的运行脚本?
  • 这将是一个老生常谈的工作。
猜你喜欢
  • 2012-06-09
  • 1970-01-01
  • 2015-12-16
  • 2013-02-04
  • 1970-01-01
  • 2014-08-12
  • 2013-11-18
  • 2011-01-28
  • 1970-01-01
相关资源
最近更新 更多