You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

为何JavaScript中SQLite3的UPDATE操作this.changes值不稳定?求解决

SQLite3 UPDATE操作中this.changes有时为0的原因及解决办法

问题原因分析

  • 内存与数据库数据不同步:你的代码先从内存data数组查找noteId,找到后才执行数据库UPDATE,但如果data数组存在该noteId,但数据库中对应的记录已删除或从未存在,UPDATE语句找不到匹配行,this.changes就会返回0。
  • 点赞逻辑的状态不一致:你依赖内存里的item.hasLiked判断是否执行点赞,但用户刷新页面后,内存data数组会重新加载,hasLiked状态重置,此时若用户再次点击,即使cookie存在,仍会触发UPDATE;但如果数据库中noteId对应的记录不存在,依然会出现this.changes=0的情况。
  • noteId类型不匹配:你把noteId转成了整数,但如果数据库中noteId字段是字符串类型,WHERE noteId = ?的匹配会失败,导致UPDATE无生效行。

解决办法

1. 先校验数据库记录是否存在

执行UPDATE前先查询数据库,确认noteId对应的记录存在,避免无意义的UPDATE操作:

app.post("/like/:noteId", (req, res) => {
  shuf = false;
  const noteId = parseInt(req.params.noteId.trim());
  // 先检查cookie是否已点赞,直接拦截重复请求
  const hasLiked = req.cookies[`liked_${noteId}`];
  if (hasLiked === "true") {
    return res.redirect("/");
  }

  // 先查询数据库确认记录存在
  db.get("SELECT * FROM data WHERE noteId = ?", [noteId], (err, row) => {
    if (err) {
      console.log(err.message);
      return res.status(500).send("服务器错误");
    }
    if (!row) {
      return res.status(404).send("目标笔记不存在");
    }

    // 执行UPDATE操作
    db.run("UPDATE data SET Like = Like + 1 WHERE noteId = ?", [noteId], function(err) {
      if (err) {
        console.log(err.message);
        return res.status(500).send("点赞失败");
      }
      if (this.changes === 0) {
        return res.status(500).send("点赞未生效,请重试");
      }
      console.log(`Row(s) updated: ${this.changes}`);

      // 更新内存数据
      const itemIndex = data.findIndex(item => item.noteId === noteId);
      if (itemIndex !== -1) {
        const item = data[itemIndex];
        item.like++;
        item.hasLiked = true;
        // 移到数组开头
        data.splice(itemIndex, 1);
        data.unshift(item);
      }

      res.cookie(`liked_${noteId}`, "true");
      res.redirect("/");
    });
  });
});

2. 统一状态判断逻辑

不要仅依赖内存data数组的状态,结合cookie和数据库查询结果双重校验,避免重复点赞或无效操作:

  • 优先通过cookie判断用户是否已点赞,直接拦截重复请求
  • 数据库查询作为兜底校验,确保操作的有效性

3. 确保noteId类型匹配

检查数据库中noteId字段的类型:

  • 如果数据库中是整数类型,保持parseInt转换
  • 如果是字符串类型,去掉parseInt,直接使用req.params.noteId.trim()作为参数传入

4. 调整内存数据更新时机

将内存数据的更新放在数据库操作成功之后,避免数据库操作失败但内存数据已修改的不一致情况。

内容的提问来源于stack exchange,提问作者Fathin

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.22 07:10:34