这里写自定义目录标题
thinkPHP6 批量更新数据
thinkPHP6升级以后,核心框架改版了很多语法内容,尤其是6.0.3+之后,不允许在模型里直接调用query和execute执行原生SQL方法(注:6.0.8这个版本有一个重大的bug,在这个版本里,不能使用query和execute执行原生SQL方法,不论你是否在model还是直接调用实例Db类,都不行,所以建议后面项目升级版本,跳过6.0.8这个版本,当时把我整的差点怀疑人生,不能执行原生SQL,简直反人类,不过幸好在6.0.9之后修复了这个问题),扯远了,咋们言归正传,thinkPHP对批量执行更新,框架里是没有这个操作的,只能直接封装,代码如下:
批量更新示例代码如下
示例代码 PHP封装函数
。
/**
* 执行原生SQL查询
* @param string $sql SQL语句
* @return mixed
*/
function db_query(string $sql)
{
$db_prefix = db_prefix();
// 替换表前缀
$sql = str_replace("__PREFIX__",$db_prefix,$sql);
return Db::query($sql);
}
/**
* 执行原生SQL
* @param string $sql SQL语句
* @return mixed
*/
function db_execute(string $sql)
{
$db_prefix = db_prefix();
// 替换表前缀
$sql = str_replace("__PREFIX__",$db_prefix,$sql);
return Db::execute($sql);
}
/**
* 获取表前缀
* @return mixed
*/
function db_prefix(){
return facade\Env::get("database.prefix");
}
/**
* 批量更新数据
* @param string $table_name 表名
* @param array $data 更新的数据
* @param string $field 作为更新条件的字段,注:主键pk
* @return mixed
*/
function db_batch_update(string $table_name,array $data,string $field)
{
// 生成SQL
$sql = 'UPDATE __PREFIX__'.$table_name." SET ";
$fields = $casesSql = [];
foreach ($data as $key => $value) {
// 指定更新字段不存在
if (!isset($value[$field])){
continue;
}
// 记录更新字段
$temp = $value[$field];
if(!in_array($temp,$fields)){
$fields[]=$temp;
}
// 拼接更新字段条件
foreach ($value as $k => $v) {
// 更新条件字段不更新
if ($k == $field){
continue;
}
$temp = $value[$field];
// 拼接CASE,默认CASE头
$caseWhen = isset($casesSql[$k]) ? $casesSql[$k] : "`{$k}` = (CASE `{$field}` ";
// 拼接WHEN
$caseSql = sprintf(
"%s WHEN '%s' THEN '%s' ",
$caseWhen,$temp,$v
);
$casesSql[$k] = $caseSql;
}
}
if (!$casesSql){
return false;
}
$endSql = [];
// 拼接结束END
foreach ($casesSql as $key=>$val){
$endSql[] = $val." END)";
}
$sql .= implode(',',$endSql);
unset($data,$casesSql,$endSql);
// 拼接WHERE
$str = implode(',', array_map('change_to_quotes', $fields ));
$sql .=" WHERE `{$field}` IN ({$str})";
// 创建并执行完整SQL
$res = db_execute($sql);
return $res;
}
/**
* 字符串加上单引号
* @param $str
* @return string
*/
function change_to_quotes($str) {
return sprintf("'%s'", $str);
}
注:本示例代码,是是基于PHP8开发的,低版本的项目,请适当修改入参,可以根据自己的业务需求对代码进行进一步优化,其他框架也可以使用,只需要修改一下执行SQL即可。