我有两个外部托管的第三方.txt
文件,这些文件是由我以外的其他人不定期更新的。我编写了一个脚本来提取此信息,对其进行操作,并创建适合在数据库中使用的合并数据数组。我不是在寻找确切的代码,而是一个好的过程的描述,如果它不存在,将有效地从这个数组中插入一个新行,如果有任何值更改,则更新表中的行,或删除如果数据数组中不再存在该行中的一行。
数据相当简单,具有以下结构:
map (string) | route (string) | time (decimal) | player (string) | country (string)
map
和route
组合必须是唯一的。
有没有办法完成所有需要的操作,而无需遍历所有外部数据和我数据库中表的所有数据?如果没有,那么最有效的方法是什么?
以下是我所写的内容。除了删除部分之外,它会处理所有内容:
require_once('includes/db.php');
require_once('includes/helpers.php');
$data = array_merge(
custom_parse_func('http://example1.com/ex.txt'),
custom_parse_func('http://example2.com/ex.txt')
);
try {
$dsn = "mysql:host=$dbhost;dbname=mydb";
$dbh = new PDO($dsn, $dbuser, $dbpass);
$dbh->setAttribute(PDO::ATTR_EMULATE_PREPARES, false);
$dbh->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
foreach ($data as $value) {
$s = $dbh->prepare('INSERT INTO table SET map=:map, route=:route, time=:time, player=:player, country=:country ON DUPLICATE KEY UPDATE map=:map2, route=:route2, time=:time2, player=:player2, country=:country2');
$s->execute(array(
':map' => $value['map'],
':route' => $value['route'],
':time' => $value['time'],
':player' => $value['player'],
':country' => $value['country'],
':map2' => $value['map'],
':route2' => $value['route'],
':time2' => $value['time'],
':player2' => $value['player'],
':country2' => $value['country']
));
}
} catch(PDOException $e) {
echo $e;
}
答案 0 :(得分:2)
你提到你正在使用MySQL,它有一个方便的INSERT ... ON DUPLICATE KEY UPDATE ...
语句(documentation here)。您将不得不迭代您的数据集(但不是现有的表)。我会处理它与@Tim B做的有点不同......
创建一个temporary table来保存新数据。
循环播放新数据并将其插入新表格
运行从临时表插入现有表的INSERT ... ON DUPLICATE KEY UPDATE ...
语句 - 负责插入新记录和更新的更改记录。
运行DELETE FROM [existing table] t1 LEFT JOIN [temporary table] t2 ON [whatever key(s) you have] WHERE t2.id IS NULL
- 这将删除现有表中未出现在临时表中的所有内容。
关于临时表的好处是它们会在连接关闭时自动删除(还有一些其他很好的功能,比如对其他连接不可见)。
这个方法的另一个好处是,在将数据库插入到步骤1的表中之后,您可以在数据库中执行一些(或全部)数据操作。执行此类操作通常更快更简单通过SQL而不是循环并更改数组中的值。
答案 1 :(得分:1)
最简单的方法是截断表,然后插入所有值。这将满足您的所有要求。
假设这不可行,那么您需要记住哪些行已被修改,可以使用标志,版本号或时间戳来完成。例如:
更新表格,设置"更新"每行标记为0
为每个项目(http://dev.mysql.com/doc/refman/5.6/en/insert-on-duplicate.html)循环执行upsert。在每个upsert中将标志设置为1。
删除数据库中的每个条目,并将标志设置为0。