CodeIgniter-活动记录插入如果是新的或更新重复

时间:2015-03-28 15:13:07

标签: mysql codeigniter

是否可以在CodeIgniter中执行活动记录查询,如果现有记录已经存在,则更新现有记录,如果不存在则为给定密钥插入?

我知道这可以通过首先查询找到现有记录来完成,但我正在寻求最有效的方法。

8 个答案:

答案 0 :(得分:29)

基本上您正在寻找的可能是 INSERT ... ON DUPLICATE KEY UPDATE - 只要您使用的是MySQL,并且您的ID是桌面上的唯一键。

您必须手动构建查询并传递给$this->db->query()函数,而不是像DB驱动程序的辅助函数那样内置的活动记录。

示例:

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

答案 1 :(得分:17)

如果您使用Codeigniter 3.0或更高版本,您可能需要考虑使用“$ this-> db-> replace()”。根据用户指南:

“此方法执行REPLACE语句,它基本上是(可选)DELETE + INSERT的SQL标准,使用PRIMARY和UNIQUE键作为决定因素。在我们的例子中,它将使您免于实现复杂逻辑的需要使用select(),update(),delete()和insert()调用的不同组合。“

换句话说,

  • 如果它不存在,则会插入新记录。
  • 如果确实存在,则根据其主键或唯一键更新它。

直接开箱即用,如:

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

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

不需要电池!!!

答案 2 :(得分:3)

我不知道Codeigniter Active Record Class是否使用此方法或不检查codeigniter docs中包含活动记录类的方法

但是你可以通过扩展共识的核心模型来实现这一目标。 通过使用这种方式,您可以将此方法用于扩展此模型类的所有模型。 只需将MY_model.php放入application / core /并编写以下代码即可。

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;

  }
}

创建上述文件后您必须将所有模型父类更改为新的扩展模型,即MY_Model

class some_model extends MY_Model

注意:您必须从结果中选择主键并将其置于where条件中。

这非常关键,所以当我从控制器获取数据时,我只是检查它是否有ID,如果Id存在,那么我解除了更新查询,如果没有,那么我解雇了插入查询。

最好的运气

答案 3 :(得分:3)

你可以做得更简单:

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

答案 4 :(得分:1)

我正在使用这种方法:

  1. 使用您要更新的mytable的{​​{1}}和unique id密钥为您的表unique配置

  2. 尝试使用column xyz插入数组$data,避免重复

    INSERT IGNORE INTO

    如果$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); 中的值不存在

  3. ,则会插入一行
  4. 如果插入了行,则使用函数column xyz返回insert_id(),如果没有插入行则更新。

    id

答案 5 :(得分:0)

这是一种我希望可以实现相同的方法

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

答案 6 :(得分:0)

更新了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);

答案 7 :(得分:0)

如果MarcosSánchezUrquiola在his answer中建议的替换解决方案由于您具有自动增量列而不适用于您,则以下是最干净的方法,同时避免了自己引用和消毒输入内容,让Codeigniter做到这一点。

$table = 'database.table'; // Usually you would have this in you model
$primary_key = 'id'; // You would also have this in you model

$data = [
    'id' => '14',
    'name' => 'John Smith',
    'email' => 'john.smith@devnullmail.com',
];

// get keys and remove primary_key if it has been included in the data array
$updates_array = array_filter( array_keys($data), function($fieldName) use ($primary_key) { return $fieldName !== $primary_key; });
array_walk($updates_array, function(&$item){ $item = "{$item}=VALUES({$item})"; } );

$sql = $this->db->insert_string($table, $data) . ' ON DUPLICATE KEY UPDATE ' . implode(', ', $updates_array);

$this->db->query($sql);

/*
Generates an insert statement with the following at the end:
    ON DUPLICATE KEY UPDATE
        name=VALUES(name),
        email=VALUES(email)
This way you work with the values you already supplied to $this->db->insert_string
*/