2010-07-29 9 views
16

Ho un CodeIgniter/modello PHP e voglio inserire alcuni dati nel database.Come utilizzerei ON DUPLICATE KEY UPDATE nel mio modello CodeIgniter?

Tuttavia, ho questo set nella mia query SQL 'crudo':

ON DUPLICATE KEY UPDATE duplicate=duplicate+1 

Sto usando CodeIgniter e sto convertendo tutte le mie precedenti query SQL in-controller per ActiveRecord. C'è un modo per farlo all'interno del modello basato su ActiveRecord?

Grazie!

Jack

risposta

2

Il link al thread del forum di cui sopra è rotto. Non conosco un modo migliore di usare semplicemente db-> query per la chiamata, se qualcuno ha una soluzione migliore, per favore pubblica questo.

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

Spero che questo aiuti qualcuno a cercare una soluzione a questo.

4

È possibile modificare la funzione di registrazione attiva con un'aggiunta minima:

DB_driver.php aggiungere all'interno della classe:

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

interrogazione funzione di ricerca (... e aggiungere subito all'inizio:

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

e, infine, in DB_active_rec.php aggiungere funzioni:

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

Ora è possibile utilizzarlo come:

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

Pro: utilizza tutti i convalida record attivo Contro: Non è il migliore (il più corretto) modo di estendere la funzione, perché se avete intenzione di aggiornare questi file, sarà necessario ripetere la procedura .

43

È possibile aggiungere il "ON DUPLICATE" dichiarazione senza modificare alcun file 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(); 

Spero che possa aiutare qualcuno.

+0

sì ha aiutato :) – Nishant

+0

Questa è la soluzione più pulita finché CI non aggiunge questo. Vota su/ – Nemke

+0

Che è dubbio perché lasciano il supporto :(http://ellislab.com/blog/entry/ellislab-seeking-new-owner-for-codeigniter – Shaffe

0

A seguito del frammento collegati da Pickett, ho fatto un paio di modifiche per:

1) Aggiornare a utilizzare il nuovo Query Builder (CI 3), precedentemente conosciuto come Active Record.

2) Si può ora passare un array associativo (chiave => valore) o un array di array associativi. Nel secondo modulo, esegue un multi-aggiornamento.

L'ho provato solo con mysqli e funziona bene.

Questo pezzo di codice va nel sistema/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; 
} 

E questo va nel file /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); 
} 

allora si può fare questo per un singolo inserto riga/aggiornamento:

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

O questo per un multi inserto/aggiornamento:

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

Il processo di lavoro di seguito per me in 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

Qui di seguito è un frammento di codice che uso ogni volta per l'aggiornamento su duplicati:

$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: colonna id deve essere primaria o univoca

0

Utilizzando $this->db->query() e parametri, questo è il modo in cui lo faccio. i primi 4 parametri sono per la parte inserto e gli ultimi tre parametri sono ripetuti per 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); 
Problemi correlati