¿Cómo usaría ON DUPLICATE KEY UPDATE en mi modelo CodeIgniter?

Tengo un CodeIgniter / PHP Model y quiero insertar algunos datos en la base de datos.

Sin embargo, tengo este conjunto en mi consulta SQL ‘en bruto’:

ON DUPLICATE KEY UPDATE duplicate=duplicate+1 

Estoy usando CodeIgniter y estoy convirtiendo todas mis consultas SQL previas en controlador a ActiveRecord . ¿Hay alguna forma de hacerlo desde dentro del modelo basado en ActiveRecord?

¡Gracias!

Jack

Puede agregar la statement “ON DUPLICATE” sin modificar ningún archivo core.

 $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(); 

Espero que ayude a alguien.

Puede modificar la función de grabación activa con una mínima adición:

DB_driver.php agrega dentro de la clase:

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

encuentre la consulta de función (… y añádalo desde el principio:

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

y finalmente en la función de agregar 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); } 

Ahora puedes usarlo como:

$ this-> db-> insert_or_update (‘table’, array $ data);

Pros: utiliza toda la validación del registro activo Contras: no es la mejor (la más adecuada) forma de ampliar la función, porque si planea actualizar estos archivos, tendrá que volver a realizar el procedimiento.

El siguiente proceso me funciona en 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(); } 

El enlace al hilo del foro anterior está roto. No sé de una mejor manera que simplemente usar db-> query para la llamada, si alguien tiene una mejor solución, por favor publíquela.

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

Espero que esto ayude a alguien a buscar una solución a esto.

A continuación se muestra un fragmento de código que uso cada vez para actualizar los duplicados:

 $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)); 

Nota: el id columna debe ser primario o único

Siguiendo el fragmento vinculado por Pickett, hice algunas modificaciones a:

1) Actualícela para usar el nuevo Query Builder (CI 3), anteriormente conocido como Active Record.

2) Ahora puede pasar una matriz asociativa (clave => valor) o una matriz de matrices asociativas. En la segunda forma, realiza una actualización múltiple.

Solo lo probé con mysqli, y funciona bien.

Este fragmento de código va en 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; } 

Y esto va al archivo /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); } 

Luego puede hacer esto para una inserción / actualización de una sola fila:

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

O esto para una inserción / actualización múltiple:

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

Usando $this->db->query() y parámetros, así es como lo hago. los primeros 4 parámetros son para la parte de inserción y los últimos tres parámetros se repiten para la parte de 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);