Как я могу использовать ON DUPLICATE KEY UPDATE в моей модели CodeIgniter?
У меня есть CodeIgniter/PHP Model, и я хочу вставить некоторые данные в базу данных.
Однако у меня есть этот набор в моем "сыром" SQL-запросе:
ON DUPLICATE KEY UPDATE duplicate=duplicate+1
Я использую CodeIgniter и конвертирую все мои предыдущие SQL-запросы в контроллер в ActiveRecord. Есть ли способ сделать это из модели ActiveRecord?
Спасибо!
Джек
Ответы
Ответ 1
Вы можете добавить инструкцию "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();
Я надеюсь, что он поможет кому-то.
Ответ 2
Вы можете настроить активную запись с минимальным добавлением:
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 add:
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 ( "таблица", данные массива $);
Плюсы: использует всю активную проверку записи
Минусы: это не лучший (самый правильный) способ расширения функции, потому что если вы планируете обновлять эти файлы, вам придется выполнить повторную процедуру.
Ответ 3
Следующий процесс работает для меня в 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();
}
Ответ 4
Ссылка на тему форума вверху нарушена. Я не знаю лучшего способа, чем просто использовать db- > query для вызова, если у кого-то есть лучшее решение, напишите об этом.
$result = $this->CI->db->query(
"INSERT INTO tablename (id, name, duplicate) VALUES (1, 'Joe', 1) ".
"ON DUPLICATE KEY UPDATE duplicate=duplicate+1");
Надеюсь, это поможет кому-то найти решение.
Ответ 5
Ниже приведен фрагмент кода, который я использую каждый раз для обновления дубликатов:
$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
должен быть первичным или уникальным
Ответ 6
Следуя фрагменту, связанному с Пикеттом, я сделал несколько изменений:
1) Обновите его, чтобы использовать новый Query Builder (CI 3), ранее известный как Active Record.
2) Теперь вы можете передать ассоциативный массив (key = > value) или массив ассоциативных массивов. Во второй форме он выполняет множественное обновление.
Я тестировал его только с помощью mysqli, и он работает хорошо.
Этот фрагмент кода находится в системе /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')
));
Ответ 7
Используя $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);