Codeigniter — пакетное обновление с несколькими условиями Where

Во-первых, документации Codeigniter по update_batch не существует. kenjis был достаточно любезен, чтобы предоставить некоторую документацию и отправить ее в репозиторий. Надеюсь, скоро потянут.

Кто-нибудь знает, как добавить несколько условий where в команду 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.

Источники:


person zechdc    schedule 15.09.2011    source источник


Ответы (3)


Вы не можете добавить несколько предложений 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)
person Chris Schmitz    schedule 15.09.2011
comment
Облом, было бы неплохо добавить четвертый параметр в конце. Если вы используете прямой SQL, вы можете добавить AND в конец запроса UPDATE. Кажется, это дает желаемый эффект, например: UPDATE mytable SET ... WHERE id IN(1,2,3) AND mycategory = 44 - person taber; 12.09.2012

Я использую 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');
}
person Rodrigo Prazim    schedule 10.06.2016
comment
Помните, мой второй индекс является статическим значением - person Rodrigo Prazim; 10.06.2016
comment
Вау, чувак, ты нестандартный мыслитель. Я бы никогда не подумал об этом. Спасибо - person json2021; 15.07.2016
comment
если бы вы только могли придумать способ, при котором второй индекс тоже был бы динамическим! - person Afghan Dev; 28.06.2017
comment
было бы лучше, если бы вы включили третий параметр update_batch в аргумент вашего public function update_data - person John Christian De Chavez; 10.01.2018
comment
Это не работает, взгляните на мое сообщение на форуме: forum.codeigniter.com/thread-68561 .html - person Rodrigo Prazim; 11.01.2018
comment
Причина, по которой предложение where удаляется в последующих пакетах, заключается в том, что запрос «где» очищается в цикле пакетной обработки. Смотрите мой ответ для объяснения того, что происходит. - person Ray Li; 21.09.2019
comment
Ваше решение еще компактнее, но лучше изменить мой код, чем код CodeIgniter, потому что обновление фреймворка становится все сложнее. Тем не менее, мое решение является лучшим. - person Rodrigo Prazim; 23.09.2019

Несколько условий where нарушаются в 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) и не работают для последующих пакетов.

Есть два возможных решения:

  1. Используйте 4-й параметр batch_size для update_batch и передайте большое число, например 100 000, чтобы все запросы обрабатывались в первом пакете, а условие WHERE не очищалось.
  2. Обновите ошибочную строку, чтобы восстановить исходные условия 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;
        }

Надеюсь, это помогло!

person Ray Li    schedule 21.09.2019