【问题标题】:How can I INSERT if row doesn't exist, else UPDATE that row?如果行不存在,我如何插入,否则更新该行?
【发布时间】:2021-06-30 16:20:27
【问题描述】:

在前端,每​​当我按下提交问题的答案时,它都会创建 1 个包含这些列的 result_ID。

result_ID 是自动递增的,question_ID 是与 questions 表中相同 question_ID 的关系。

如果这是用户第一次选择答案,它将创建一个 answer_result(我在 answer_ID 中解析)和 answer_checkResult(值 1 或 0 来识别它的正确或不正确),以及一个 history_ID 来分别识别每条记录。

History_ID 是具有 quiz_ID(用于识别主题)和 user_ID 的不同表

示例:History_ID 221 有 4 个问题,有 4 个答案和 4 个 answer_result。

我不知道的是,如果该行不存在,我如何创建一个情况,它将运行 INSERT INTO 情况,否则如果它已经存在(因为用户可以在 1 中多次更改答案问题),它会更新。我刚刚只创建了 INSERT INTO 选项,但我不知道如何在此模型中同时使用 INSERT INTO 进行更新。

这是我创建的history_result.model,我不知道如何创建一个if-else来同时更新和创建......

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

这就是我创建 history_result 控制器的方法

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

无论如何我可以做到这一点吗?谢谢。

【问题讨论】:

标签: mysql sql node.js express model-view-controller


【解决方案1】:

是的,你可以。

但首先您必须将 question_ID 设为 PRIMARY KEY。传递给 db.query 的第二个参数是包含 history_result 属性的对象

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

【讨论】:

  • 为什么我必须将 question_ID 设为 PRIMARY KEY?因为在我的表中我已经将 result_ID 设置为 PRIMARY KEY,请您为我解释更多,因为我想象的 ON DUPLICATE KEY 有点混乱。
  • @Bunny 你必须在question_ID 上创建一个带有UNIQUE 属性的index,不必将其设为PRIMARY_KEY。您可以保留您的实际主键,重复检查将在索引上触发
  • 但是 question_ID 可以重复,如果我让它独一无二,它会破坏整个表格。 question_ID 是我从问题表中提取的外键。
  • 例如question_ID 14,history_ID 221,可以有不同的answer_result和answer_checkResult,而question_ID 14,history_ID 229,也可以有不同的answer_result和answer_checkResult! (在我的图像中)
【解决方案2】:

首先,请阅读MySQL Insert or Update on duplicate-key update tutorial
或者这个Official MySQL INSERT ... ON DUPLICATE KEY UPDATE Statement document

现在回到你的问题。据我了解,history_result 表中的question_IDhistory_ID 对是独一无二的,因为每个用户在测验中只会给出一个问题的答案。

首先,您需要为表的对 (question_ID, history_ID) 创建唯一索引约束。

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

然后发出INSERT ON DUPLICATE KEY UPDATE 语句来达到效果。

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

如果 question_ID = 14 和 history_ID = 12 行已经存在(用户已经回答了这个问题的场景),它将触发更新answer_result。如果没有,它将插入一条新记录。

如果新行在 UNIQUE 索引或 PRIMARY KEY 中重复,则满足 DUPLICATE KEY 约束。在我们的例子中,它是 (question_ID, history_ID) 的唯一索引,因此会调用 UPDATE 语句。

【讨论】:

  • 对不起,但在我的表中,唯一的 result_ID 是 UNIQUE 并且是 PRIMARY KEY,question_IDanswer_IDhistory_ID 与其他表有关系。
  • 是的,因为result_ID 是唯一的并且是主键。所以在您的INSERT ON DUPLICATE KEY UPDATE 语句中,您只需要传递question_IDanswer_resulthistory_ID。如果您还在 insert into 语句中包含 result_ID,则会引发 DUPLICATE KEY 约束。因为我们只想更新具有相同question_IDhistory_ID 的记录是否已经存在。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2012-12-17
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-02-06
  • 1970-01-01
相关资源
最近更新 更多