Codeigniter - пакетное обновление с несколькими условиями
Во-первых, документация Codeigniter на update_batch не существует. kenjis был достаточно любезен, чтобы предоставить некоторую документацию и отправить ее в репозиторий. Надеюсь, они скоро потянутся.
Кто-нибудь знает, как добавить несколько, где условия для команды Codeigniters update_batch?
Желаемое использование:
$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();
Создает строку обновления на основе данных, которые вы поставляете, и запускает запрос. Вы можете передать в функцию массив или объект. Вот пример использования массива:
$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.
Источники:
Ответы
Ответ 1
Вы не можете добавить несколько аргументов where к update_batch()
. Он принимает только строку в качестве третьего параметра для предложения where, поэтому я уверен, что нет способа сделать это так, как этот метод в настоящее время написан.
Из источника :
/**
* 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)
Ответ 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'
ОБНОВИТЬ
У меня возникла проблема при попытке добавить более 100 записей с помощью update_batch, например:
$data = [1=>a,2=>b ... 200=>zz];
Первый звонок (с ГДЕ):
// 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'
Второй звонок (без ГДЕ):
// 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');
}
Ответ 3
Несколько, когда условия нарушены в update_batch
, потому что запрос 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 нарушающая линия находится на 1940 в DB_query_builder.php
. Это приводит к очень неожиданному поведению, когда условия WHERE работают для первого обработанного пакета (по умолчанию 100) и не выполняются для последующих пакетов.
Есть два возможных решения:
- Используйте 4-й параметр
batch_size
в update_batch
и передайте большое число, например 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;
}
Надеюсь, это помогло!