Используйте INSERT ON DUPLICATE KEY UPDATE для вставки нескольких записей.

Структура моей таблицы

таблица: отметки введите здесь описание изображения

Моя цель: я хочу вставить или обновить несколько записей с условием

в настоящее время я проверяю этот запрос

1-й шаг

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

2-й шаг

if 
    records found by matching above criteria i just update record by my new values 
else
    insert new record into my table 

Он будет работать нормально. но я хочу сократить код и оптимизировать его в один запрос. это возможно или нет? Я нашел это в документации MySQL INSERT... ON DUPLICATE KEY UPDATE. если это решение. как я могу достичь по запросу?

Примечание. Я использую фреймворк 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`)

person Babu    schedule 21.04.2014    source источник
comment
Первый шаг: создайте уникальный индекс (студент, параметр), а затем просто попробуйте вставить, как вы это сделали бы, ON DUPLICATE KEY UPDATE SET mark=VALUES(mark)   -  person Wrikken    schedule 21.04.2014
comment
@Wrikken, как установить комбинацию двух столбцов как уникальный файл . потому что разные студенты имеют одинаковые параметры. комбинация студента и параметра только уникальна. я не знаком с индексацией. пожалуйста, нужно больше информации. Спасибо   -  person Babu    schedule 21.04.2014
comment
@Wrikken, я редактирую свой вопрос. пожалуйста, просмотрите его. он не обновляет существующую запись. но правильно пропустить повторяющуюся запись. я добавляю уникальный индекс для полей student и param .   -  person Babu    schedule 21.04.2014
comment
ALTER TABLE marks ADD UNIQUE (student, param);, а затем INSERT INTO marks (student, param, mark, created) VALUES (11,20,10,NOW()) ON DUPLICATE KEY UPDATE SET mark=VALUES(mark); должно работать.   -  person Wrikken    schedule 22.04.2014
comment
@Wrikken решил эту проблему. спасибо за ваш комментарий. это полезно для других   -  person Babu    schedule 22.04.2014


Ответы (2)


Прочтите эту статью Yii INSERT... ON DUPLICATE UPDATE. Они предлагают вам не использовать эту функцию. Но я хочу, чтобы он использовался, поэтому я расширил свой собственный компонент из CDbCommand и добавил метод для ON DUPLICATE KEY UPDATE:

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']);

Эта команда создаст пользователя с этими параметрами или обновит поля token и updated, если запись существует.

person Alex    schedule 21.04.2014
comment
не могли бы вы привести пример параметра для этой функции. $table, $columns, $duplicates как передать эти значения - person Babu; 21.04.2014
comment
@RyanBabu конечно, я добавил несколько примеров - person Alex; 21.04.2014
comment
перед этим нужна индексация полей? пожалуйста, просмотрите мой вопрос в отредактированном разделе. этот запрос не работает. Где я сделал ошибку, я не могу понять свою проблему здесь. ваш код полезен, я знаю. я просто запускаю этот sql в одиночку. это не обновляет существующее значение. Спасибо за ваш пример. приятно реализовать - person Babu; 21.04.2014
comment
ВСТАВИТЬ В метки(student,param,mark, created,lastmodified, status) есть ошибка: param,mark надо по 'param', 'mark' - person Alex; 21.04.2014
comment
Я попробовал еще раз, Алекс, но не обновился, затронуты только 0 строк. я обновил свой вопрос - person Babu; 21.04.2014
comment
Я узнаю свою проблему @alex, спасибо за ваш ответ, теперь я использую вашу функцию. я не обновляю другие значения. **param=значения (param), student=значения (student) ** Здесь это не нужно. оба значения одинаковы. теперь работает - person Babu; 21.04.2014

Не применяйте "INSERT... ON DUPLICATE" в своем программировании, так как это специфично для 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();
    }
person Hearaman    schedule 21.04.2014
comment
ты читал его вопрос? он сказал, что хочет сделать это в одном запросе - person Alex; 21.04.2014
comment
Спасибо за совет . моему приложению не нужна функция изменения БД. Я также использую этот тип процесса. я хочу изменить это на sql из-за скорости попадания в БД. Скорость вставки очень высока. Этот процесс кажется мне медленным. Мне нужна оптимизация. - person Babu; 21.04.2014