根据外部来源插入、更新或删除记录的正确方法是什么


What is a proper way to insert, update, or delete records based on an outside source?

我有两个外部托管的第三方.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不同的方式来处理它。。。

  1. 创建一个临时表来保存新数据。

  2. 循环浏览您的新数据并将其插入到新表中

  3. 运行一个INSERT ... ON DUPLICATE KEY UPDATE ...语句,从临时表插入到现有表中,该语句负责插入新记录和更新的更改记录。

  4. 运行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的每个条目。