我正在尝试执行以下操作。
我正在使用Web服务咨询外部数据库。 Web服务要做的就是将客户使用的ERP系统中的所有产品带给我。由于服务器和连接的速度不是很快,因此我决定要做的是基本上同步Web服务器上的数据库并在那里处理大多数操作,以便网站可以平稳运行。
一切正常,我只需要最后一步,以确保网站上的库存与ERP上可用的库存匹配。唯一的问题是当他们(客户端)删除ERP系统上的内容时。
目前,我正在考虑如果在Web服务结果中未收到产品,则从“产品”表中删除产品的理想策略(最少的资源和时间)是什么。
所以我基本上有以下过程:
我在Web服务中查询所有产品,给它们一些格式,然后将它们存储在数组中。最终大小约为600个索引。
然后,我要做的是执行一个foreach
循环并具有以下子过程。
我查询数据库以检查是否存在product_id
。
如果存在该产品,我只需使用最新信息(库存数据)对其进行更新。
如果产品不存在,请插入。
因此,我正在考虑执行以下操作,但我认为这不是理想的方法:
进行SELECT * FROM Products
并生成包含所有乘积的数组。
在结果阵列中执行一个foreach
循环,然后在每个循环中扫描ERP阵列以检查特定产品是否存在。如果不是,请删除它;如果是,我继续下一个产品。
现在考虑到在完成上述所有步骤之后,这将涉及几个嵌套的foreach
,我有点担心它可能会占用过多的内存,并且处理时间也会更长。
我当时以为也许array_diff
或array map
可以解决问题,但是我对这些功能并不真正了解,并且两个数组的结构差异很大,所以我不确定是否可以使用容易。
你们会推荐什么?
最佳答案
实际上很简单:
SELECT id FROM Products
然后,您有一个产品ID数组,例如:
[123,5679,345]
然后,当您进行更新或插入操作时,请从阵列中删除ID。
[有关更新]我查询我的数据库以检查product_id是否存在。
现在这是多余的。
有几种方法可以从数组中删除值(当您进行更新时),这就是我可能要做的方法。
if(false !== ($index = array_search($data['product_id'],$myids))){
//note the !== type comparison because array_search can return 0 for the first index, we must check for boolean false.
//find the index of the product id in our list of id's from local DB
unset($myids[$index]);
//If our incoming product_id is in the local list we Do Update
}else{
//Otherwise we Do Insert
}
如上文所述,在执行更新/插入操作时,您不再需要检查ID是否存在,因为您已经通过从数据库中获取ID数组来知道这一点。仅此一项就可以节省您(n)个查询(apx 600)。
然后,如果您还有ID,则非常简单。
//I wouldn't normally concatenate variables into SQL, in this case it's a list of int IDs from the database.
//you can of course come up with a loop to make it a prepared statement if you wish, but for the sake of simplistically, I'll leave that as an exercise for another day..
'DELETE FROM Products WHERE id IN('.implode(',', $myids).')'
并且由于您在更新时未设置这些设置,因此剩下的仅是不再存在的产品。
结论:
您别无选择(否则,请执行重复键查询或忽略异常),然后再提取产品ID。您已经在逐行执行此操作。这样一来,我们就能有效杀死2只鸟。
如果需要更多数据,则只需ID,例如,在进行更新之前,请检查产品是否已更改。然后拉出该数据,但我建议使用PDO和FETCH_GROUP选项。我不会详细介绍它,但是可以说它使您可以轻松地以这种方式构建数组:
[{product_id} => [ {product_name}, {product_price} etc..]];
基本上product_id是具有行数据嵌套数组的键,这将使查找更加容易。
这样,您可以像这样查找它。
//then instead of array_search
//if(false !== ($index = array_search($data['product_id'],$myids))){
if(isset($myids[$data['product_id']])){
unset($myids[$data['product_id']]);
//do your checks, then your update
}else{
//do inserts
}
参考文献:
http://php.net/manual/en/function.array-search.php
array_search —在数组中搜索给定值,如果成功,则返回第一个对应的键
警告此函数可能返回布尔值FALSE,但也可能返回非布尔值,其值为FALSE。请阅读有关布尔值的部分以了解更多信息。使用===运算符测试此函数的返回值。
更新
还有另一种非常好的方法,那就是添加一个名为
sync_date
的字段,现在当您进行插入或更新时,将sync_date
设置为当前数据。这样,完成后,可以删除那些具有比今天更早同步日期的产品。在这种情况下,最好在执行操作时将时间缓存起来,以便您知道确切的时间。
$time = data('Y-m-d H:i:s'); //or time() if you prefer timestamp
//use this same variable for the whole coarse of the script.
那你就可以
'DELETE from products WHERE sync_time != $time'
实际上,这可能会好一点,因为它具有更多的实用性。它是上一次运行的时间,现在您知道了。