我正在使用ThingEngineer / PHP-MySQLi-Database-Class,并且尝试使用OnDuplicate时执行多次插入。目的是在“ sku”尚不存在时插入新的产品记录。如果确实存在“ sku”,则应更新“名称”,而不是创建新条目。
MySQL模式:
CREATE TABLE `products` (
`product_pk` bigint(9) NOT NULL,
`product_id` int(20) UNSIGNED NOT NULL,
`name` varchar(255) NOT NULL,
`sku` varchar(16) NOT NULL,
`category` int(10) DEFAULT NULL,
`last_update` timestamp NOT NULL ON UPDATE CURRENT_TIMESTAMP
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci;
ALTER TABLE `products`
ADD PRIMARY KEY (`product_pk`),
ADD UNIQUE KEY `sku` (`sku`);
ALTER TABLE `products`
MODIFY `product_pk` bigint(9) NOT NULL AUTO_INCREMENT;
PHP:
$sDate = date("Y-m-d H:i:s");
$lastid = $db->rawQuery('SELECT MAX( product_id ) AS max FROM products');
(!$lastid || !isset($lastid[0]['max'])) ? $pid = 0 : $pid = $lastid[0]['max']++;
foreach ($data as $item){
if (isset($item['sku']) && !null == $item['sku']){
$prod[$pid]['product_id'] = $pid;
$prod[$pid]['sku'] = $item['sku'];
$prod[$pid]['name'] = substr($item['product-name'],0,255);
$prod[$pid]['last_update'] = $sDate;
$pid++;
}
}
$utfEncodedArray =encodeArray($prod, 'UTF-8');
$db->onDuplicate('name', 'product_pk');
$db->insertMulti('products', $utfEncodedArray);
function encodeArray($array, $type)
{
foreach($array as $key => $value)
{
if (is_array($value)){ $array[$key] = encodeArray($value, $type);}else{ $array[$key] = mb_convert_encoding($value, $type);}
}
return $array;
}
我收到的错误是:
Uncaught mysqli_sql_exception: Duplicate entry 'ABC123' for key 'sku'
这是insertMulti调用中使用的数组$ utfEncodedArray的示例:
Array(
[1] => Array
(
[product_id] => 1
[sku] => ABC123
[name] => product1
[last_update] => 2018-09-08 18:55:20
)
[2] => Array
(
[product_id] => 2
[sku] => ABC124
[name] => product2
[last_update] => 2018-09-08 18:55:20
)
)
到目前为止我尝试过的步骤:
删除“产品”表并再次创建。多次。
在onDuplicate调用中尝试使用“ sku”而不是“ product_pk”。
尝试了多种排序规则类型
尝试对“ sku”和“ product_id”使用唯一键
当我尝试此方法时,所有条目均已正确插入,但再次运行时,它会生成重复项,而不是更新现有行。不确定'sku'和'product_id'是唯一的,这是怎么发生的。
$ prod数组当前包含相同的值。因此,每次运行此程序时,我都希望看到在初次插入后每次都更新“ last_updated”列。
这是我第一次使用onDuplicate,尽管经过数小时的搜索和阅读文档,但我仍然迷失了方向。我试图让db类处理数组中的多次插入,但我不反对在迭代产品数组时尝试原始查询。
最佳答案
当然,一旦我发布了这个,我就会发现问题...
找到了数据库类的一个分支,该分支在使用onDuplicate时解决了insertMulti的问题:
should fix insertMulti() if onDuplicate() is set