2010-07-29 12 views
16

Tengo un CodeIgniter/PHP Model y quiero insertar algunos datos en la base de datos.¿Cómo usaría ON DUPLICATE KEY UPDATE en mi modelo CodeIgniter?

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

ON DUPLICATE KEY UPDATE duplicate=duplicate+1 

estoy usando CodeIgniter y estoy convirtiendo todos mis anteriores consultas SQL en el controlador de ActiveRecord. ¿Hay alguna forma de hacerlo desde dentro del modelo basado en ActiveRecord?

Gracias!

Jack

Respuesta

2

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.

4

Se pueden ajustar la función de grabación activo con adición mínima:

DB_driver.php añadir dentro de la clase:

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

función de búsqueda de consultas (... y añadir al comienzo:

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

y finalmente en DB_active_rec.php añadir la función:

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 puede usarlo como:

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

Pros: utiliza toda la validación de registro activa Contras: que no es la mejor (la más adecuada) forma de extender la función, porque si usted está planeando para actualizar estos archivos, tendrá que volver a hacer el procedimiento .

43

Puede agregar la declaración "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.

+0

sí, ayudó :) – Nishant

+0

Esta es la solución más limpia hasta que CI no lo agregue. Votar arriba 0/ – Nemke

+0

Lo cual es dudoso porque dejan de admitir :(http://ellislab.com/blog/entry/ellislab-seeking-new-owner-for-codeigniter – Shaffe

0

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

1) Actualizar a utilizar el nuevo generador de consultas (IC 3), anteriormente conocida 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 en el 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); 
} 

entonces usted puede hacer esto por una sola fila de inserción/actualización:

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

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

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

El proceso de trabajo por debajo de mí 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(); 
} 
2

A continuación se muestra un fragmento de código que utilizo para cada actualización de 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: la columna id debe ser primaria o única

0

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 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); 
Cuestiones relacionadas