Codeigniter - 具有多个 Where 条件的批量更新
Posted
技术标签:
【中文标题】Codeigniter - 具有多个 Where 条件的批量更新【英文标题】:Codeigniter - Batch Update with Multiple Where Conditions 【发布时间】:2011-11-17 13:44:47 【问题描述】:对于初学者,关于 update_batch 的 Codeigniter 文档不存在。 kenjis 提供了一些文档并将其提交到存储库。希望他们尽快把它拉出来。
有谁知道如何在 Codeigniters update_batch 命令中添加多个 where 条件?
我的预期用途:
$where = array(
'title',
'name'
);
$this->db->update_batch('mytable', $data, $where);
当我尝试此代码时,出现以下错误:
A Database Error Occurred
One or more rows submitted for batch updating is missing the specified index.
Filename: C:\wamp\www\wheel\system\database\DB_active_rec.php
Line Number: 1451
kenjis 更新批量文档:
$this->db->update_batch();
根据您提供的数据生成更新字符串,并运行查询。您可以将 array 或 object 传递给函数。下面是一个使用数组的例子:
$data = array(
array(
'title' => 'My title' ,
'name' => 'My Name 2' ,
'date' => 'My date 2'
),
array(
'title' => 'Another title' ,
'name' => 'Another Name 2' ,
'date' => 'Another date 2'
)
);
$this->db->update_batch('mytable', $data, 'title');
// Produces:
// UPDATE `mytable` SET `name` = CASE
// WHEN `title` = 'My title' THEN 'My Name 2'
// WHEN `title` = 'Another title' THEN 'Another Name 2'
// ELSE `name` END,
// `date` = CASE
// WHEN `title` = 'My title' THEN 'My date 2'
// WHEN `title` = 'Another title' THEN 'Another date 2'
// ELSE `date` END
// WHERE `title` IN ('My title','Another title')
第一个参数将包含表名,第二个是一个关联数组,第三个参数是 where 键。
来源:
kenjis 的文档更新: https://bitbucket.org/kenjis/ci-user-guide/changeset/3d579dd14afe saintnicster 的拉取请求:https://github.com/EllisLab/CodeIgniter/pull/448【问题讨论】:
【参考方案1】:您不能将多个 where 子句添加到 update_batch()
。它只接受一个字符串作为 where 子句的第三个参数,所以我确信没有办法按照当前编写方法的方式执行此操作。
来自source:
/**
* Update_Batch
*
* Compiles an update string and runs the query
*
* @param string the table to retrieve the results from
* @param array an associative array of update values
* @param string the where key
* @return object
*/
public function update_batch($table = '', $set = NULL, $index = NULL)
【讨论】:
太糟糕了,如果最后有第四个参数,那将是一个很好的补充。如果您直接使用 SQL,则可以在 UPDATE 查询的末尾添加一个“AND”。这似乎产生了预期的效果,例如:UPDATE mytable SET ... WHERE id IN(1,2,3) AND mycategory = 44
【参考方案2】:
我正在使用 codeigniter 3.1.5 并且遇到了同样的问题,但我解决了我的问题如下:
$data = array(
array(
'title' => 'My title' ,
'name' => 'My Name 2' ,
'date' => 'My date 2'
),
array(
'title' => 'Another title' ,
'name' => 'Another Name 2' ,
'date' => 'Another date 2'
)
);
$this->db->where('name','My Name 2');
$this->db->update_batch('mytable', $data, 'title');
生产它:
// Produces:
// UPDATE `mytable`
// SET `name` = CASE
// WHEN `title` = 'Another title' THEN 'Another Name 2'
// WHEN `title` = 'My title' THEN 'My Name 2'
// ELSE `name`
// END,
// `date` = CASE
// WHEN `title` = 'My title' THEN 'My date 2'
// WHEN `title` = 'Another title' THEN 'Another date 2'
// ELSE `date`
// END
// WHERE `title` IN ('My title','Another title')
// AND `name` = 'My Name 2'
更新
我在尝试使用 update_batch 添加超过 100 条记录时遇到问题,例如:
$data = [1=>a,2=>b ... 200=>zz];
第一次调用(使用 WHERE):
// Produces:
// UPDATE `mytable`
// SET `name` = CASE
// WHEN `title` = 'My title' THEN 'My Name 2'
// WHEN `title` = 'Another title' THEN 'Another Name 2'
// ELSE `name`
// END,
// `date` = CASE
// WHEN `title` = 'My title' THEN 'My date 2'
// WHEN `title` = 'Another title' THEN 'Another date 2'
// ELSE `date`
// END
// WHERE `title` IN ('My title','Another title')
// AND `name` = 'My Name 2'
第二次调用(没有 WHERE):
// Produces:
// UPDATE `mytable`
// SET `name` = CASE
// WHEN `title` = 'My title' THEN 'My Name 2'
// WHEN `title` = 'Another title' THEN 'Another Name 2'
// ELSE `name`
// END,
// `date` = CASE
// WHEN `title` = 'My title' THEN 'My date 2'
// WHEN `title` = 'Another title' THEN 'Another date 2'
// ELSE `date`
// END
// WHERE `title` IN ('My title','Another title')
试试这个:
$chunk1 = array_chunk($data,100);
for($i=0;$i < count($chunk1);$i++)
$this->upload_model->update_data($chunk1[$i],'My Name 2');
型号:
public function update_data($data='',$name='')
$this->db->where('name',$name);
$this->db->update_batch('mytable', $data, 'title');
【讨论】:
记住,我的第二个索引是静态值 哇,伙计,你是个开箱即用的思想家。我永远不会这样想。谢谢 如果你能想到第二个索引也是动态的方法! 最好将update_batch
的第三个参数包含在public function update_data
的参数中
不行,看看我的论坛帖子:forum.codeigniter.com/thread-68561.html【参考方案3】:
update_batch
中的多个 where 条件被破坏,因为批处理循环中正在清除 WHERE 查询。
这里是批量更新循环:
for ($i = 0, $total = count($this->qb_set_ub); $i < $total; $i += $batch_size)
if ($this->query($this->_update_batch($this->protect_identifiers($table, TRUE, NULL, FALSE), array_slice($this->qb_set_ub, $i, $batch_size), $index)))
$affected_rows += $this->affected_rows();
$this->qb_where = array();
请注意,传递的 WHERE 条件被 $this->qb_where = array();
清除。
在 CodeIgniter v3.1.10 中,违规行位于 DB_query_builder.php
中的 1940 上。这会产生一个非常意外的行为,其中 WHERE 条件适用于第一个处理的批次(默认 100),而后续批次则失败。
有两种可能的解决方案:
-
使用
update_batch
的第4个batch_size
参数,并传入100,000这样的大数,这样所有的查询都会在第一批中处理,不会清除WHERE条件。
更新违规行以恢复初始 WHERE 条件。
解决方案 #2 的代码:
// Save initial where conditions.
$where_holder = $this->qb_where;
// Batch this baby
$affected_rows = 0;
for ($i = 0, $total = count($this->qb_set_ub); $i < $total; $i += $batch_size)
if ($this->query($this->_update_batch($this->protect_identifiers($table, TRUE, NULL, FALSE), array_slice($this->qb_set_ub, $i, $batch_size), $index)))
$affected_rows += $this->affected_rows();
// Restore intial where conditions.
$this->qb_where = $where_holder;
希望这有帮助!
【讨论】:
【参考方案4】:Try this one also !
Suppon you have import data through csv/excel
then store all record in single array like:
Array
(
[0] => Array
(
[price] => 100.00
[part_no] => PD001
[brand] => 44
[special_price] => 90.10
)
[1] => Array
(
[price] => 200.00
[part_no] => PD002
[special_price] => 150.00
)
)
Step 2:
Call to model
$model = new CatalogModel();
$result = $model->batchUpdateData($final_array);
function batchUpdateData($array = array())
$query = $this->db->table('product');
$price = array();
$part_no = array();
$special = array();
$brand = array();
if (!empty($array))
foreach ($array as $key => $value)
$price[] = $value['price'];
$part_no[] = $value['part_no'];
$special[] = $value['special_price'];
$brand[] = $value['brand'];
$num = count($part_no);
$sql ="UPDATE product SET ";
// price colum update
$sql .=" price = CASE ";
for($i=0; $i < $num; $i++)
$sql .=" WHEN part_no = '".$part_no[$i]."' AND brand = '".$brand[$i]."' THEN '".$price[$i]."' ";
$sql .="ELSE price END ,";
// special colum update
$sql .=" special_price = CASE ";
for($i=0; $i < $num; $i++)
$sql .=" WHEN part_no = '".$part_no[$i]."' AND brand = '".$brand[$i]."' THEN '".$special[$i]."' ";
$sql .="ELSE special_price END";
$sql .=" WHERE part_no IN ('" . implode("','", $part_no) . "') ";
return $this->db->query($sql);
This will product query like:
UPDATE `product` SET `price` = CASE WHEN `part_no` = 'PD001' and `brand` = '44' THEN '100.00' WHEN `part_no` = 'PD002' and `brand` = '44' THEN '200.00' ELSE `price` END
WHERE `part_no` IN('PD001','PD002');
If this helpfull give a thumbs up
【讨论】:
请编辑您的答案,并提供有关代码功能的其他信息。见How to answer。以上是关于Codeigniter - 具有多个 Where 条件的批量更新的主要内容,如果未能解决你的问题,请参考以下文章
CodeIgniter:如何使用活动记录将一个列值移动到另一个具有 Where 条件的值
使用多个 WHERE 子句更新 Codeigniter 中的批处理
使用 CodeIgniter 的 ActiveRecord 对多个条件逻辑进行分组