简体   繁体   中英

How can I INSERT if row doesn't exist, else UPDATE that row?

At the front-end, whenever I press submit an answer to a question, it'll create 1 result_ID that has these columns.

result_ID is auto-increment, question_ID is relation with the same question_ID from questions table.

If it's the first time the user chooses the answer, it'll create an answer_result (i parse in answer_ID) and answer_checkResult (value 1 or 0 to identify it's correct or incorrect), and a history_ID to identify each record separately.

History_ID is a different table that has the quiz_ID (to identify topic) and user_ID

example: History_ID 221 has 4 questions in there, and has 4 answers with 4 answer_result.

What I don't know is how can I create a situation if the row doesn't exist, it'll run INSERT INTO situation, and else if it already exists (because the user can change the answer multiple times in 1 question), it'll UPDATE. I've just created only the INSERT INTO option, but I don't know how to do the update in this model at the same time with INSERT INTO.

在此处输入图片说明

This is my history_result.model that I've created, I don't know how to create an if-else to update and create at the same time...

history_result.model

const HistoryResult = function (history_result) {
    this.question_ID = history_result.question_ID;
    this.answer_result = history_result.answer_result;
    this.answer_checkResult = history_result.answer_checkResult;
    this.history_ID = history_result.history_ID;
};

HistoryResult.create = async (newHistoryResult, result) => {
    await db.query(
        `INSERT INTO history_result SET question_ID = ?, answer_result = ?, answer_checkResult = ?, history_ID = ?`,
        [
            newHistoryResult.question_ID,
            newHistoryResult.answer_result,
            newHistoryResult.answer_checkResult,
            newHistoryResult.history_ID,
        ],
        (err, data) => {
            if (err) {
                result(err, null);
                return;
            } else {
                return result(null, data);
            }
        }
    );
};

And here's how I create the history_result controller

const HistoryResult = require("../models/history_result.model");
exports.createHistoryResult = async (req, res) => {
    let { history_ID } = req.params;
    let { question_ID, answer_result, answer_checkResult } = req.body;
    let historyResult = new HistoryResult({
        question_ID: question_ID,
        answer_result: answer_result,
        answer_checkResult: answer_checkResult,
        history_ID: history_ID,
    });
    HistoryResult.create(historyResult, (err, data) => {
        if (err) {
            res.status(500).send({
                message: err.message || "Error while creating result",
            });
        }
        res.send(data);
    });
};

Is there anyways I can achieve this? Thanks.

Yes, you can.

but first you have to make question_ID as PRIMARY KEY. And second parameter that you pass to db.query is object that contains history_result's attributes

INSERT INTO history_result
SET ?
ON DUPLICATE KEY UPDATE
    answer_result = VALUES(answer_result),
    answer_checkResult = VALUES(answer_checkResult),
    history_ID = VALUES(history_ID)

db.query(query, objectHere, (err, data) => {
    if (err) {
        result(err, null);
        return;
    } else {
        return result(null, data);
    }
}))

First, please read the MySQL Insert or Update on duplicate-key update tutorial ,
or this Official MySQL INSERT ... ON DUPLICATE KEY UPDATE Statement document

Now back to your question. As I understand, the question_ID and history_ID pair in the history_result table would be unique, as each user will only give one answer to a question in a quiz.

First you would need to create a unique index constraints of the pair (question_ID, history_ID) of your table.

ALTER TABLE history_result
ADD CONSTRAINT uc_question_history
UNIQUE (question_ID,history_ID);

And then issue an INSERT ON DUPLICATE KEY UPDATE statement to achive the effect.

INSERT INTO history_result
    (
        question_ID, answer_result, history_ID
    )
VALUES
    (14, 21, 12)
ON DUPLICATE KEY UPDATE
    answer_result = 21;

If the question_ID = 14 and history_ID = 12 row already existed (scenario that user has already answer this question), it will trigger to update the answer_result . If not, it will insert a new record.

The DUPLICATE KEY constraint is met if a new row is a duplicate in UNIQUE index or PRIMARY KEY. In our case, it's the unique index of (question_ID, history_ID), hence the UPDATE statement will be invoked.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM