How would I use ON DUPLICATE KEY UPDATE in my CodeIgniter model?

前端 未结 8 1521
暖寄归人
暖寄归人 2020-11-30 07:27

I have a CodeIgniter/PHP Model and I want to insert some data into the database.

However, I have this set in my \'raw\' SQL query:

ON DUPLICATE KEY U         


        
相关标签:
8条回答
  • 2020-11-30 08:04

    You can tweak the active record function with minimal addition:

    DB_driver.php add inside the class:

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

    find function query( ...and add at the very beginning:

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

    and finally in DB_active_rec.php add function:

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

    Now you can use it as:

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

    Pros: uses all the active record validation Cons: it is not the best (the most proper) way of extending the function, because if you are planning to update these files, you will have to redo the procedure.

    0 讨论(0)
  • 2020-11-30 08:05

    The link to the forum thread above is broken. I don't know of a better way than just using db->query for the call, if someone has a better solution, please post that.

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

    I hope this helps someone looking for a solution to this.

    0 讨论(0)
  • 2020-11-30 08:12

    The below process work for 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();
    }
    
    0 讨论(0)
  • 2020-11-30 08:15

    Below is a code snippet I use everytime for update on duplicates:

    $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: column id must be primary or unique

    0 讨论(0)
  • 2020-11-30 08:19

    Following the snippet linked by Pickett, I made a few modifications to:

    1) Update it to use the new Query Builder (CI 3), formerly known as Active Record.

    2) You can now pass an associative array (key => value) or an array of associative arrays. In the second form, it performs a multi-update.

    I only tested it with mysqli, and it works well.

    This piece of code goes in 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;
    }
    

    And this goes into the /system/database/DB_query_builder.php file:

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

    Then you can do this for a single row insert/update:

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

    Or this for a multi insert/update:

    $this->db->on_duplicate('table', array(
        array('column1' => 'value', 'column2' => 'value'),
        array('column1' => 'value', 'column2' => 'value')
    ));
    
    0 讨论(0)
  • 2020-11-30 08:22

    Using $this->db->query() and parameters, this is how I do it. the first 4 parameters are for the insert part and the last three parameters are repeated for the on duplicate key update part.

    $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);
    
    0 讨论(0)
提交回复
热议问题