工作中实现业务,大多会有这样的一段逻辑:
如果某条数据在数据库里存在,就更新,否则就插入。
用原生mysql语句实现就是:
`INSERT INTO ... ON DUPLICATE KEY UPDATE ...`
如果直接用if判断来写,也就是如下:
if(dataExist){
//update data
}else{
//insert data
}
为了方便快捷,就直接用thinkphp框架里的dupliate函数了。
第一次是我自己先入为主了,以为duplicate函数参数,就是传入唯一索引所涉及到的字段名:
但其实正确的写法理应如下:
$resVal = $modelBlock->strict(false)->duplicate($insertData)->insert($insertData, true);
上面这段代码,一定要数据库表存在唯一索引,且$insertData包含索引的字段数据(equipment_id和field_name),功能才生效。
本以为坑是被我踩得明明白白的了,结果我今天遇到类似的业务,代码写成如下,数据库死活无法更新:
$condition = [
'equipment_id' => $lemsData['id'],
'data_date' => $dayDate,
];
$saveData = [
'equipment_id' => $lemsData['id'],
'data_date' => $dayDate,
'device_id' => $lemsData['device_id'],
'is_system' => 1, //标志为系统修改
'status' => 1,
'value' => $runTime,
'remark' => 'merge run time',
'description' => json_encode($listRunRecord),
'update_time' => DateUtil::getCurrentDatetime()
];
$res = $modelManual->strict(false)->duplicate($condition)->insert($saveData, true);
equipment_id和data_date就是数据库的唯一性组合索引unique key的相关字段。
最后检查上次的笔记,才发现上次前后都用的同一个数组,这个时候才感觉这方法设计得好冗余。
然后我突发奇想,想试试前后数组数据不一样会怎样?它到底是更新哪一个?
试完之后,感觉更奇葩了。测试代码大致如下:
$saveData1 = [
'equipment_id' => $lemsData['id'],
'data_date' => $dayDate,
'device_id' => $lemsData['device_id'],
'is_system' => 1, //标志为系统修改
'status' => 1,
'value' => $runTime,
// 'remark' => 'merge run time23',
'description' => json_encode($listRunRecord),
'update_time' => '2023-01-01 02:00:00'
];
$saveData = [
'equipment_id' => $lemsData['id'],
'data_date' => $dayDate,
// 'device_id' => $lemsData['device_id'],
// 'is_system' => 1, //标志为系统修改
// 'status' => 1,
// 'value' => $runTime,
'remark' => 'merge run time11',
// 'description' => json_encode($listRunRecord),
// 'update_time' => DateUtil::getCurrentDatetime()
];
$res = $modelManual->strict(false)->duplicate($saveData1)->insert($saveData, true);
经过详细测试,发现insert方法的参数,必须要有唯一索引性相关的字段数据,否则数据无法更新。
原本我直接以为,这个是作为duplicate函数的参数的,结果人家放在了后面。
更新的数据,放在insert参数里,全都“无效”,哪怕$saveData里有的数据在$saveData1里没有,也没法更新。
反而都是在duplicate函数参数里的数据,才可以被更新到,看下图:
insert/save方法是最直观意义上的插入和保存,居然参数的数据全是废物(除了索引字段),大家就说奇葩不奇葩。
本为了省事,想少写3行代码,一来简洁,二来节省时间,结果却折腾了一整个下午,真有点让人哭笑不得。