Как мне использовать ON DUPLICATE KEY UPDATE в моей модели CodeIgniter? - PullRequest
20 голосов
/ 29 июля 2010

У меня есть модель CodeIgniter / PHP, и я хочу вставить некоторые данные в базу данных.

Однако у меня есть этот набор в моем «сыром» SQL-запросе:

ON DUPLICATE KEY UPDATE duplicate=duplicate+1

Я использую CodeIgniter и преобразую все мои предыдущие запросы SQL в контроллере в ActiveRecord . Есть ли способ сделать это из модели на основе ActiveRecord?

Спасибо!

Jack

Ответы [ 8 ]

52 голосов
/ 04 апреля 2013

Вы можете добавить оператор "ON DUPLICATE" без изменения каких-либо основных файлов.

$sql = $this->db->insert_string('table', $data) . ' ON DUPLICATE KEY UPDATE duplicate=LAST_INSERT_ID(duplicate)';
$this->db->query($sql);
$id = $this->db->insert_id();

Надеюсь, это кому-нибудь поможет.

4 голосов
/ 10 февраля 2013

Вы можете настроить функцию активной записи с минимальным добавлением:

DB_driver.php добавить внутри класса:

protected $OnlyReturnQuery = false;
public function onlyReturnQuery($return = true)
{
    $this->OnlyReturnQuery = $return;
}

найти запрос функции (... и добавить в самом начале:

    if ($this->OnlyReturnQuery) {
        $this->OnlyReturnQuery = false;
        return $sql;
    }

и, наконец, в DB_active_rec.php добавить функцию:

public function insert_or_update($table='', $data=array())
{
    $this->onlyReturnQuery();
    $this->set($data);
    $insert = $this->insert($table);
    $this->onlyReturnQuery();
    $this->set($data);
    $update = $this->update($table);
    $update = preg_replace('/UPDATE.*?SET/',' ON DUPLICATE KEY UPDATE',$update);
    return $this->query($insert.$update);
}

Теперь вы можете использовать его как:

$ this-> db-> insert_or_update ('таблица', массив $ data);

Плюсы: использует все активные проверки записей Минусы: это не лучший (самый правильный) способ расширения функции, потому что, если вы планируете обновить эти файлы, вам придется повторить процедуру.

3 голосов
/ 18 июня 2016

У меня нижеописанный процесс работает в Codeigniter 3.0.6

public function updateOnDuplicate($table, $data ) {
    if (empty($table) || empty($data)) return false;
    $duplicate_data = array();
    foreach($data AS $key => $value) {
        $duplicate_data[] = sprintf("%s='%s'", $key, $value);
    }

    $sql = sprintf("%s ON DUPLICATE KEY UPDATE %s", $this->db->insert_string($table, $data), implode(',', $duplicate_data));
    $this->db->query($sql);
    return $this->db->insert_id();
}
2 голосов
/ 18 июля 2016

Ниже приведен фрагмент кода, который я использую каждый раз для обновления дубликатов:

$sql = "insert into  table_name (id, name) values(".$id.",'".$name."') on duplicate key update id=".$id.",name='".$name."'";
//Executing queries
$result = $this->db->query($sql, array($id, $name)); 

Примечание: столбец id должен быть основным или уникальным

2 голосов
/ 03 мая 2011

Ссылка на ветку форума выше не работает.Я не знаю лучшего способа, чем просто использовать db-> query для звонка, если у кого-то есть лучшее решение, пожалуйста, опубликуйте его.

$result = $this->CI->db->query(
    "INSERT INTO tablename (id, name, duplicate) VALUES (1, 'Joe', 1) ".
    "ON DUPLICATE KEY UPDATE duplicate=duplicate+1");

Я надеюсь, что это поможет кому-то найти решение дляэто.

1 голос
/ 10 мая 2016

После фрагмента, связанного с Pickett, я сделал несколько изменений:

1) Обновите его, чтобы использовать новый построитель запросов (CI 3), ранее известный как Active Record.

2) Теперь вы можете передать ассоциативный массив (ключ => значение) или массив ассоциативных массивов.Во второй форме он выполняет многократное обновление.

Я протестировал его только с mysqli, и он хорошо работает.

Этот фрагмент кода находится в system / database / drivers / mysqli /mysqli_driver.php

function _duplicate_insert($table, $values)
{
    $updatestr = array();
    $keystr    = array();
    $valstr    = array();

    foreach($values as $key => $val)
    {
        $updatestr[] = $key." = ".$val;
        $keystr[]    = $key;
        $valstr[]    = $val;
    }

    $sql  = "INSERT INTO ".$table." (".implode(', ',$keystr).") ";
    $sql .= "VALUES (".implode(', ',$valstr).") ";
    $sql .= "ON DUPLICATE KEY UPDATE ".implode(', ',$updatestr);

    return $sql;
}

function _multi_duplicate_insert($table, $values)
{
    $updatestr = array();
    $keystr    = array();
    $valstr    = null;
    $entries   = array();

    $temp = array_keys($values);
    $first = $values[$temp[0]];

    foreach($first as $key => $val)
    {
        $updatestr[] = $key." = VALUES(".$key.")";
        $keystr[]    = $key;
    }

    foreach($values as $entry)
    {
        $valstr = array();
        foreach($entry as $key => $val)
        {
            $valstr[] = $val;
        }
        $entries[] = '('.implode(', ', $valstr).')';
    }

    $sql  = "INSERT INTO ".$table." (".implode(', ',$keystr).") ";

    $sql .= "VALUES ".implode(', ',$entries);
    $sql .= "ON DUPLICATE KEY UPDATE ".implode(', ',$updatestr);

    return $sql;
}

И это входит в файл /system/database/DB_query_builder.php:

function on_duplicate($table = '', $set = NULL )
{
    if ( ! is_null($set))
    {
        $this->set($set);
    }

    if (count($this->qb_set) == 0)
    {
        if ($this->db_debug)
        {
            return $this->display_error('db_must_use_set');
        }
        return FALSE;
    }

    if ($table == '')
    {
        if ( ! isset($this->qb_from[0]))
        {
            if ($this->db_debug)
            {
                return $this->display_error('db_must_set_table');
            }
            return FALSE;
        }

        $table = $this->qb_from[0];
    }

    $is_multi = false;
    foreach (array_keys($set) as $k => $v) {
        if ($k === $v) {
            $is_multi = true; //is not assoc
            break;
        }
    }

    if($is_multi)
    {
        $sql = $this->_multi_duplicate_insert($this->protect_identifiers($table, TRUE, NULL, FALSE), $this->qb_set );
    }
    else
    {
        $sql = $this->_duplicate_insert($this->protect_identifiers($table, TRUE, NULL, FALSE), $this->qb_set );
    }

    $this->_reset_write();
    return $this->query($sql);
}

Затем вы можете сделать это для вставки / обновления одной строки:

$this->db->on_duplicate('table', array('column1' => 'value', 'column2' => 'value'));

Или это для мульти вставки / обновления:

$this->db->on_duplicate('table', array(
    array('column1' => 'value', 'column2' => 'value'),
    array('column1' => 'value', 'column2' => 'value')
));
0 голосов
/ 28 сентября 2018

Просто сделано -

    $updt_str = '';
    foreach ($insert_array as $k => $v) {
        $updt_str = $updt_str.' '.$k.' = '.$v.',';
    }
    $updt_str = substr_replace($updt_str,";", -1);
    $this->db->query($this->db->insert_string('table_name', $insert_array).' ON DUPLICATE KEY UPDATE '.$updt_str);
0 голосов
/ 05 декабря 2017

Используя $this->db->query() и параметры, я так и делаю. первые 4 параметра относятся к вставляемой детали, а последние три параметра повторяются для on duplicate key update детали.

$sql = "insert into application_committee ".
       "(application_id, member1_id, member2_id, member3_id) values (?, ?, ?, ?)".
       " on duplicate key update member1_id = ?, member2_id = ?, member3_id = ?";

$this->db->query($sql, array($appid, $member_1, $member_2, $member_3, 
                 $member_1, $member_2, $member_3);
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...