人间工作P 人间工作P
主站 (opens new window)
首页
  • Bukkit开发教程
投喂
关于
  • 分类
  • 标签
  • 时间线
  • 友情链接

人间工作P

我每天都好困… 最近在学习和进行 VOCALOID 创作
主站 (opens new window)
首页
  • Bukkit开发教程
投喂
关于
  • 分类
  • 标签
  • 时间线
  • 友情链接
  • 关于在 MySQL/SQLite 将数据表当成 Map 来用的记录

    • 数据表定义
      • 读取
        • 写入
          • MySQL
          • SQLite
        • 删除
        MrXiaoM
        2025-12-13
        开发
        目录

        关于在 MySQL/SQLite 将数据表当成 Map 来用的记录

        之前没怎么研究,查查官方文档,写篇博文总结一下

        虽然说 redis (opens new window) 可能会更合适在数据库里存键值对并随时更新,但是我不想额外开一个 redis,我想我的插件用户也不会想要额外开一个 redis,所以有了这一篇博文。

        # 数据表定义

        仅用作示例,凑合着看吧。

        --- 我比较喜欢用 ` 来包裹表名、列名等等名称,以免跟关键字冲突。
        CREATE TABLE if NOT EXISTS `example`(
          `key` VARCHAR(48) PRIMARY KEY,
          `foo` VARCHAR(64),
          `bar` VARCHAR(64)
        );
        
        1
        2
        3
        4
        5
        6

        # 读取

        直接用 SELECT 语句查询,这个没有任何争议。

        SELECT * FROM `example` WHERE `key`=?;
        
        1

        # 写入

        因为有主键的原因,如果你直接 INSERT 的话会因为主键重复而报错,直接 UPDATE 的话会因为找不到条目而无法更新,这是争议比较严重的地方。

        MySQL 和 SQLite 各家都有各家的解决方案,如下所示。在实际编写代码时,按连接的数据库类型执行不同语句即可。

        # MySQL

        使用 ON DUPLICATE KEY UPDATE 语句即可,该语句即使在 MySQL 5.7 都可以使用,文档如下:

        • MySQL 5.7: INSERT ... ON DUPLICATE KEY UPDATE Statement (opens new window)

        在 ON DUPLICATE KEY UPDATE 子句中的赋值表达式中,您可以使用 VALUES(col_name) 用于在 INSERT ... ON DUPLICATE KEY UPDATE 语句中,作为引用 INSERT 列值的函数。换句话说,ON DUPLICATE KEY UPDATE 子句中的 VALUES( col_name ) 指的是 col_name 的值。使得插入时不会发生重复键冲突。该函数在插入多行数据时尤其有用。

        INSERT INTO `example`(`key`,`foo`,`bar`) VALUES(?,?,?)
          ON DUPLICATE KEY UPDATE `foo`=VALUES(`foo`), `bar`= VALUES(`bar`);
        
        1
        2

        至关重要的是 ON DUPLICATE KEY UPDATE 后面的东西,你可以填 column=?,手动传入值来更新,也可以填 column=VALUES(column) 自动获取值来更新,总之要填你需要更新哪些列的值。

        # SQLite

        使用 INSERT OR REPLACE INTO 语句即可,该语句在 SQLite 3.0.0 (2004年) 以前就有了,文档如下:

        • SQLite: The ON CONFLICT Clause (opens new window)

        对于 INSERT 和 UPDATE 命令,关键字 ON CONFLICT 被替换为 OR,以使语法更易读。例如,不再使用INSERT ON CONFLICT IGNORE,而是使用 INSERT OR IGNORE 。关键字虽然不同,但子句的含义保持不变。

        当发生唯一键 (UNIQUE) 或主键 (PRIMARY KEY) 约束冲突时,REPLACE 算法会在插入或更新当前行之前删除导致约束冲突的现有行,然后命令继续正常执行。如果发生非空 (NOT NULL) 约束冲突,REPLACE 冲突解决机制会将 NULL 值替换为该列的默认值;如果该列没有默认值,则使用 ABORT 算法。如果发生检查键 (CHECK) 约束或外键约束冲突,REPLACE 冲突解决机制与 ABORT 算法类似。

        换句话说,使用这个语句,SQLite 只会给你自动处理冲突情况,无法跟 MySQL 一样选择冲突时只更新哪些列,不过这也好,通常情况下不需要选择只更新哪些列,全部更新就完事了。

        INSERT OR REPLACE INTO `example`(`key`,`foo`,`bar`) VALUES(?,?,?);
        
        1

        是的,这就是全部。SQLite 的冲突处理跟 MySQL 比起来感觉很糙,但很实用。

        # 删除

        依然没有争议,使用 DELETE 语句进行删除即可。

        DELETE FROM `example` WHERE `key`=?;
        
        1
        编辑 (opens new window)
        #Java#MySQL#SQLite
        上次更新: 2025/12/14, 00:00:16
        最近更新
        01
        在 Blockbench 中,将网格(mesh)转换为方块(cube)
        11-30
        02
        将你的闲置手机变成麦克风
        11-23
        03
        我的直播设备架构分享
        11-18
        更多文章>
        Theme fork from Vdoing | Copyright © 2018-2025 人间工作P | 友情链接
        • 跟随系统
        • 浅色模式
        • 深色模式
        • 阅读模式