【问题标题】:How would I use ON DUPLICATE KEY UPDATE in my CodeIgniter model?如何在我的 CodeIgniter 模型中使用 ON DUPLICATE KEY UPDATE?
【发布时间】:2011-03-22 15:33:27
【问题描述】:

我有一个 CodeIgniter/PHP 模型,我想向数据库中插入一些数据。

但是,我在“原始”SQL 查询中设置了这个:

ON DUPLICATE KEY UPDATE duplicate=duplicate+1

我正在使用 CodeIgniter 并将我之前的所有控制器内 SQL 查询转换为 ActiveRecord。有没有办法在基于 ActiveRecord 的模型中做到这一点?

谢谢!

杰克

【问题讨论】:

标签: mysql activerecord codeigniter model


【解决方案1】:

您可以在不修改任何核心文件的情况下添加“ON DUPLICATE”语句。

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

我希望它会帮助某人。

【讨论】:

  • 由于这是谷歌上“在重复键上插入”的最高结果,因此不扩展此答案以迎合那些只希望在重复键上插入并返回“id”的人是不明智的在重复。 => ON DUPLICATE KEY UPDATE duplicate=LAST_INSERT_ID(duplicate)
【解决方案2】:

以下过程在 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();
}

【讨论】:

  • 这项工作适合我。只需将此代码复制并粘贴到模型文件中,然后像其他函数一样从控制器调用。
【解决方案3】:

您可以通过最少的添加来调整活动记录功能:

在类里面添加DB_driver.php:

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

find function query( ...并在最开始添加:

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

最后在 DB_active_rec.php 中添加函数:

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

现在您可以将其用作:

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

优点: 使用所有活动记录验证 缺点: 这不是扩展功能的最佳(最合适)方式,因为如果您打算更新这些文件,则必须重做该过程。

【讨论】:

    【解决方案4】:

    根据 Pickett 链接的 sn-p,我对以下内容进行了一些修改:

    1) 更新它以使用新的查询生成器 (CI 3),以前称为 Active Record。

    2) 您现在可以传递关联数组(键 => 值)或关联数组的数组。在第二种形式中,它执行多重更新。

    我只用mysqli测试过,效果很好。

    这段代码在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;
    }
    

    这会进入 /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);
    }
    

    然后您可以为单行插入/更新执行此操作:

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

    或者这个用于多插入/更新:

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

    【讨论】:

    【解决方案5】:

    上述论坛帖子的链接已损坏。我不知道比仅使用 db->query 进行呼叫更好的方法,如果有人有更好的解决方案,请发布。

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

    我希望这对寻找解决方案的人有所帮助。

    【讨论】:

      【解决方案6】:

      以下是我每次用于更新重复项的代码 sn-p:

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

      注意:id 列必须是主列或唯一列

      【讨论】:

        【解决方案7】:

        使用$this->db->query() 和参数,我就是这样做的。前 4 个参数用于插入部分,后三个参数重复用于 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);
        

        【讨论】:

          【解决方案8】:

          搞定 -

              $updt_str = '';
              foreach ($insert_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', $insert_array).' ON DUPLICATE KEY UPDATE '.$updt_str);
          

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 2011-02-12
            • 1970-01-01
            • 1970-01-01
            • 2012-07-08
            • 2011-05-16
            • 1970-01-01
            • 1970-01-01
            相关资源
            最近更新 更多