我有两个外部托管的第三方.txt
文件,它们由我以外的其他人不定期更新。我已经编写了一个脚本,它可以提取这些信息,对其进行操作,并创建一个适合在数据库中使用的合并数据数组。我不是在寻找确切的代码,而是描述一个好的过程,该过程可以有效地从这个数组中插入一个新行(如果它不存在),更新表中的一行(如果任何值发生了变化),或者删除表中的行(如果它不再存在于数据数组中)。
数据相当简单,具有以下结构:
map (string) | route (string) | time (decimal) | player (string) | country (string)
其中CCD_ 3和CCD_。
是否有任何方法可以执行所有需要的操作,而不必循环遍历所有外部数据和数据库中表中的所有数据?如果没有,最有效的方法是什么?
以下是我所写的内容。它处理除删除部分以外的所有内容:
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;
}
您提到您正在使用MySQL,它有一个方便的INSERT ... ON DUPLICATE KEY UPDATE ...
语句(此处为文档)。您将不得不迭代您的数据集合(但不能迭代现有的表)。我会用与@Tim B不同的方式来处理它。。。
-
创建一个临时表来保存新数据。
-
循环浏览您的新数据并将其插入到新表中
-
运行一个
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执行这类操作通常更快、更简单,而不是在数组中循环并更改值。
最简单的方法是截断表,然后插入所有值。这将处理您的所有要求。
假设这是不可行的,那么您需要记住哪些行已经被修改,这可以使用标志、版本号或时间戳来完成。例如:
-
更新表格,在每行上将"更新"标志设置为0
-
循环完成每件商品的追加销售(http://dev.mysql.com/doc/refman/5.6/en/insert-on-duplicate.html)。在每次追加销售中将标志设置为1。
-
从数据库中删除标志设置为0的每个条目。