2010-07-29 6 views
16

J'ai un modèle CodeIgniter/PHP et je veux insérer des données dans la base de données.Comment utiliser ON DUPLICATE KEY UPDATE dans mon modèle CodeIgniter?

Cependant, j'ai cet ensemble dans mon « brut » requête SQL:

ON DUPLICATE KEY UPDATE duplicate=duplicate+1 

J'utilise CodeIgniter et je suis en train de convertir tous mes précédents contrôleur requêtes SQL à ActiveRecord. Existe-t-il un moyen de le faire à partir du modèle basé sur ActiveRecord?

Merci!

Jack

Répondre

2

Le lien au fil de discussion ci-dessus est cassé. Je ne connais pas de meilleure façon que d'utiliser db-> requête pour l'appel, si quelqu'un a une meilleure solution, s'il vous plaît poster.

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

J'espère que ceci aide quelqu'un qui cherche une solution à ceci.

4

Vous pouvez modifier la fonction d'enregistrement actif avec ajout minimal:

DB_driver.php ajouter dans la classe:

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

requête fonction de recherche (... et ajouter au début:

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

et enfin en fonction DB_active_rec.php ajouter:

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

Maintenant, vous pouvez l'utiliser comme:

$ this-> db-> insert_or_update ('table', tableau de données de $);

Plus: utilise toutes les validation d'enregistrement actif Inconvénients: il n'est pas le meilleur (le plus propre) manière d'étendre la fonction, parce que si vous envisagez de mettre à jour ces fichiers, vous devrez recommencer la procédure .

43

Vous pouvez ajouter l'instruction "ON DUPLICATE" sans modifier les fichiers 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(); 

J'espère que ça va aider quelqu'un.

+0

oui ça a aidé :) – Nishant

+0

Ceci est la solution la plus propre jusqu'à ce que CI n'ajoute pas cela. Votez o/ – Nemke

+0

Ce qui est douteux parce qu'ils abandonnent le soutien :(http://ellislab.com/blog/entry/ellislab-seeking-new-owner-for-codeigniter – Shaffe

0

Après l'extrait lié par Pickett, je fait quelques modifications à:

1) Mettre à jour pour utiliser le nouveau Générateur de requêtes (CI 3), anciennement connu sous le nom Active Record.

2) Vous pouvez maintenant passer un tableau associatif (clé => valeur) ou un tableau de tableaux associatifs. Dans la deuxième forme, il effectue une mise à jour multiple. Je l'ai seulement testé avec mysqli, et ça marche bien.

Ce morceau de code va dans 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; 
} 

Et cela va dans le fichier /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); 
} 

Ensuite, vous pouvez le faire pour une seule insertion de ligne/mise à jour:

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

Ou ceci pour un multi insertion/mise à jour:

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

Le dessous de processus de travail pour moi dans 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

est Ci-dessous un extrait de code que j'utilise chaque fois que la mise à jour sur les doublons:

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

Note: la colonne id doit être primaire ou unique

0

En utilisant $this->db->query() et les paramètres, voici comment je le fais. les 4 premiers paramètres sont pour la pièce d'insertion et les trois derniers paramètres sont répétés pour la pièce 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); 
Questions connexes