我正在使用第三方 RESTful API 数据更新 MySQL 数据库表。此更新每天触发几次,因此为了使该过程更容易,我决定在插入新的“新鲜”API 数据之前简单地截断数据库表。然而,这导致了两个主要问题:
a) 进程执行时表变空(这是一个实时站点),
b) MySQL 服务器有时无法在执行插入时截断表。这会导致记录重复,有时甚至是四倍。
我可以将截断和插入放入一个 MySQL 事务中,但这仍然不能解决问题 (a)。
我决定以不同的方式解决这个问题:
首先,我将 API 数据和本地数据收集到两个结构相同的数组中,按键 (ASC) 和值 (ASC) 排序。这是一个例子:
$local = [
['categoryId' => '547d8fd5','programId' => '0714f2cb'],
['categoryId' => '547d8fd5','programId' => '0914f2cb'],
]
$remote = [
['categoryId' => '547d8fd5','programId' => '0714f2cb'],
['categoryId' => '547d8fd5','programId' => '0814f2cb'],
]
然后我将使用以下方法比较两个数组:
public static function arrayDiffAssocRecursive($array1, $array2)
{
foreach($array1 as $key => $value) {
if (is_array($value)) {
if (!isset($array2[$key])) {
$difference[] = $value;
} elseif(!is_array($array2[$key])) {
$difference[] = $value;
} else {
$new_diff = self::arrayDiffAssocRecursive($value, $array2[$key]);
if ($new_diff != FALSE) {
$difference[] = $array1[$key];
}
}
} elseif (!isset($array2[$key]) || $array2[$key] != $value) {
$difference[] = $value;
}
}
return !isset($difference) ? null : $difference;
}
为了获取需要添加的记录,我将按以下顺序使用参数调用上述方法:
$add = Comparator::arrayDiffAssocRecursive($remote, $local);
为了获取需要删除的记录,我将翻转参数:
$delete = Comparator::arrayDiffAssocRecursive($local, $remote);
只要两个数组排序相等且记录数相同,该方法就有效,但是如果其中一个或另一个缺少一条或多条记录,则所有剩余记录将不匹配,因此标记为删除和添加,不管它们是否保持不变。这个方法虽然有效,但我还是觉得效率低下。
我希望看到的是一种可以比较两个数组并返回不匹配记录的方法,无论数组的顺序或记录总数如何。这是可行的还是我以完全错误的方式处理这个问题?
最佳答案
使用replace into而不是insert into。只要您有一个不变的主键,那么它就会根据主键进行更新。如果主键已经存在,则执行更新,否则执行插入。
关于php - 在没有顺序或键匹配的情况下比较多维数组,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/49063005/