web-dev-qa-db-fra.com

CodeIgniter - insertion d'enregistrement active si nouvelle ou mise à jour sur duplicata

Est-il possible de faire une requête active record dans CodeIgniter qui mettra à jour un enregistrement existant s'il en existe déjà un ou insérer si ce n'est pas le cas, pour la clé donnée?

Je comprends que cela pourrait être fait en recherchant d’abord un enregistrement existant, mais je recherche l’approche la plus efficace.

21
user4718286

Ce que vous recherchez peut être essentiellement INSERT ... ON DUPLICATE KEY UPDATE - à condition que vous utilisiez MySQL et que votre identifiant soit une clé unique sur la table.

Vous devez construire manuellement la requête et passer à la fonction $this->db->query() à la place de tout enregistrement actif intégré, tel que les fonctions d'assistance du pilote de base de données.

Exemple:

$sql = 'INSERT INTO menu_sub (id, name, desc, misc)
        VALUES (?, ?, ?, ?)
        ON DUPLICATE KEY UPDATE 
            name=VALUES(name), 
            desc=VALUES(desc), 
            misc=VALUES(misc)';

$query = $this->db->query($sql, array( $id, 
                                       $this->validation->name, 
                                       $this->validation->desc, 
                                       $this->validation->misc
                                      ));
27

Si vous utilisez Codeigniter 3.0 ou supérieur, vous pouvez envisager d'utiliser "$ this-> db-> replace ()". Selon le mode d'emploi:

"Cette méthode exécute une instruction REPLACE, qui est essentiellement le standard SQL pour DELETE + INSERT (facultatif), en utilisant les clés PRIMARY et UNIQUE comme facteur déterminant. Dans notre cas, cela vous évitera de devoir implémenter des logiques complexes avec différentes combinaisons d'appels select (), update (), delete () et insert (). "

En d'autres termes, 

  • S'il n'existe pas, il insère un nouvel enregistrement.
  • S'il existe, il le met à jour en fonction de sa clé primaire ou unique.

Il suffit de l’utiliser tout de suite comme:

$data = array(
        'title' => 'My title',
        'name'  => 'My Name',
        'date'  => 'My date'
);

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

Aucune pile requise !!!

16

Vous pouvez le faire plus simplement:

$sql = $this->db->insert_string(table, $array) . ' ON DUPLICATE KEY UPDATE ' .
implode(', ', $array);
$this->db->query($sql);
3
Milaza

Je ne sais pas si la classe d'enregistrement actif de Codeigniter utilise cette méthode ou non. Consultez la documentation de codeigniter pour les méthodes contenant dans la classe d'enregistrement active

Mais vous pouvez obtenir ce résultat en étendant les modèles de base de codigniter . En utilisant cette méthode, vous pouvez utiliser cette méthode pour tous les modèles qui étendent cette classe de modèles . Placez simplement MY_model.php dans application/core/et écrivez le code suivant.

Class MY_Model extends CI_Model
{
  public function insert_update($data)
  {
       // code for checking existing record.
       if(//existing record)
           fire the update query
       else
           fire the insert query

       return insert/update id;

  }
}

après avoir créé le fichier ci-dessus, vous devez modifier la classe parente Tous vos modèles par le nouveau modèle étendu, par exemple, MY_Model.

class some_model extends MY_Model

NOTE: Vous devez sélectionner la clé primaire parmi les résultats et la placer dans la condition où.

C'est très critique, donc ce que je fais quand je reçois les données du contrôleur, je vérifie simplement si l'ID est présent ou non, puis j'ai lancé la requête de mise à jour, sinon j'ai lancé la requête d'insertion.

BONNE CHANCE

3
siddhesh

J'utilise cette approche:

  1. configurez votre table mytable avec les clés unique id et unique pour le column xyz que vous souhaitez mettre à jour

  2. essayez d'insérer un tableau $data, en utilisant INSERT IGNORE INTO, évitez les doublons

    $insert_query = $this->db->insert_string('bt_ical_list', $data);
    $insert_query = str_replace('INSERT INTO','INSERT IGNORE INTO',$insert_query);
    $this->db->query($insert_query); 
    

    cela insère une ligne, si la valeur dans column xyz n'existe pas 

  3. utilisez la fonction insert_id() pour renvoyer une id si une ligne a été insérée, mettez à jour si aucune ligne n'a été insérée.

    if(!$this->db->insert_id()){
        $query=$this->db    ->where('xyz', $data['xyz'])
                            ->update('my_table',$data);
    };  
    
1
Vickel

Mise à jour de la réponse de Milaza -

    $updt_str = '';
    foreach ($array as $k => $v) {
        $updt_str = $updt_str.' '.$k.' = '.$v.',';
    }
    $updt_str = substr_replace($updt_str,";", -1);
    $this->db->query($this->db->insert_string('table_name', $array).' ON DUPLICATE KEY UPDATE '.$updt_str);
0
WC2

Voici une méthode que j'espère peut accomplir la même chose

   /**
    * Used to insert new row if a duplicate entry is encounter it performs an update
    * @param string $table table name as string
    * @param array $data associative array of data and columns
    * @return mixed 
    */
   private function updateOnExist($table, $data)
   {
        $columns    = array();
        $values     = array();
        $upd_values = array();
        foreach ($data as $key => $val) {
            $columns[]    = $this->db->escape_identifiers($key);
            $val = $this->db->escape($val);
            $values[]     = $val;
            $upd_values[] = $key.'='.$val;
        }
        $sql = "INSERT INTO ". $this->db->dbprefix($table) ."(".implode(",", $columns).")values(".implode(', ', $values).")ON DUPLICATE KEY UPDATE".implode(",", $upd_values);
        return $this->db->query($sql);
}
0
jdialogc