Php 使用「;插入。。。“关于重复密钥更新”;插入多条记录的步骤

Php 使用「;插入。。。“关于重复密钥更新”;插入多条记录的步骤,php,mysql,yii,insert-update,Php,Mysql,Yii,Insert Update,我的表格结构 表:马克 我的目标: 我想插入或更新具有该条件的多个记录 我目前正在接受此查询的检查 第一步 SELECT * FROM `marks` WHERE `student` =115 AND `param` =1 第二步 if records found by matching above criteria i just update record by my new values else insert new record into my table 会

我的表格结构

表:马克

我的目标: 我想插入或更新具有该条件的多个记录

我目前正在接受此查询的检查

第一步

SELECT * FROM `marks` WHERE `student` =115 AND `param` =1
第二步

if 
    records found by matching above criteria i just update record by my new values 
else
    insert new record into my table 
会很好的。但我想减少代码并将其优化为单个查询。有没有可能? 我在MySQL文档插入中找到了这个。。。在重复密钥更新时。如果这是一个解决方案。如何通过查询实现

注意:我使用的是Yii框架。也欢迎Yii的建议

编辑: 此查询不会更新行。但要避免插入正确工作

INSERT INTO marks(`student`,`param,mark`,`created`,`lastmodified`,`status`) 
VALUES 
(11,30,10,'00-00-00 00:00:00','00-00-00 00:00:00','U')
ON DUPLICATE KEY UPDATE `mark`=VALUES(`mark`)
检查这篇文章。他们建议您不要使用此功能。但我想使用它,所以我从CDbCommand扩展了我自己的组件,并添加了重复密钥更新的方法:

public function insertDuplicate($table, $columns, $duplicates)
{
    $params=array();
    $names=array();
    $placeholders=array();
    foreach($columns as $name=>$value)
    {
        $names[]=$this->getConnection()->quoteColumnName($name);
        if($value instanceof CDbExpression)
        {
            $placeholders[] = $value->expression;
            foreach($value->params as $n => $v)
                $params[$n] = $v;
        }
        else
        {
            $placeholders[] = ':' . $name;
            $params[':' . $name] = $value;
        }
    }

    $d = array();
    foreach($duplicates as $duplicate)
    {
        $d[] = '`' . $duplicate . '` = VALUES(`'.$duplicate.'`)';
    }
    $sql='INSERT INTO ' . $this->getConnection()->quoteTableName($table)
        . ' (' . implode(', ',$names) . ') VALUES ('
        . implode(', ', $placeholders) . ') ON DUPLICATE KEY UPDATE ' . implode(', ', $d);
    return $this->setText($sql)->execute($params);
}
用法示例:

Yii::app()->db->createCommand()->insertDuplicate('user', [
   'id' => $this->id,
   'token' => $token,
   'updated' => date("Y-m-d H:i:s"),
], ['token', 'updated']);
此命令将使用此参数创建用户,或更新
令牌
更新的
字段(如果记录存在)。

不要在编程中实现“在重复时插入…”,因为它是特定于MySQL的。当您从MySQL迁移到其他数据库时,您的程序无法按照

像这样试试

    function actionName()
    {
        $id=$_POST['marks']['id']; //Pick the ID from your form values
        $model = Marks::model()->findByPk($id); //Check the records in the Marks table
        if (!$model) //If not found create a new Model for insertion. If records are there it will update the model
            $model = new Marks();
        $model->attributes = $_POST['marks']; //Assign the form values to attributes
        $model->save();
    }

第一步:在(student,param)上创建一个唯一的索引,然后像您一样尝试插入,
on replicate KEY UPDATE SET mark=VALUES(mark)
@Wrikken如何将两列组合设置为唯一的。因为不同的学生有相同的参数。student和param组合都是唯一的。我不太熟悉索引。请你需要更多的信息。thanks@Wrikken我编辑我的问题。请复习一下。它不会更新现有记录。但它可以正确地跳过重复条目。我为字段student和param添加唯一索引。
ALTER TABLE marks add unique(student,param),然后
在重复键更新上插入标记(学生、参数、标记、创建)值(11,20,10,NOW()),设置标记=值(标记)应该可以工作。@Wrikken此问题已解决。谢谢你的评论。这对其他人很有用。请给出此函数的示例参数$表$columns$重复了如何传递这些values@RyanBabu当然,在此之前我添加了一些示例,是否需要任何字段索引?请复习我在编辑部分的问题。这个查询不起作用。在我犯错误的地方,我无法理解我的问题。我知道你的代码很有用。我只是单独运行sql。它不会更新现有值。谢谢你的例子。很高兴在标记中插入(
student
param,mark
created
lastmodified
status
)有一个错误:
param,mark
它必须通过'param',mark'我发现了我的问题@alex谢谢你的回答现在我使用你的函数。我不会更新其他值。**
param
=值(
param
),
student
=值(
student
)**这里不需要。两个值相同。现在它起作用了你读过他的问题吗?他说他想在一个问讯箱里问你的意见。我的应用程序不需要数据库更改功能。我也在使用这种类型的过程。我想把它改成sql,因为DB命中率很高。插入率非常高。这个过程对我来说似乎很慢。我需要优化。