微信为什么使用 SQLite 保存聊天记录?

2023年 8月 13日 82.0k 0

来源:modern-sql.com/blog/2019-01/sqlite-in-2018

SQLite 是一个被大家低估的数据库,但有些人认为它是一个不适合生产环境使用的玩具数据库。事实上,SQLite 是一个非常可靠的数据库,它可以处理 TB 级的数据,但它没有网络层。接下来,本文将与大家共同探讨 SQLite 在过去一年中新的 SQL 功能。‍

SQLite “只是”一个库,它不是传统意义上的服务器。因此,在某些场合下,它确实不合适。但是,在相当多的其他场合,它却是合适的选择。SQLite 号称是部署和使用广泛的数据库引擎。我认为这很有可能,因为 SQLite 没有版权的限制。

无论何时,只要开发者想使用 SQL 在文件中存储结构化的数据,SQLite 应是方案。

SQLite 的 SQL 方言也非常强大。它比 MySQL 早四年就开始支持 with 语句。近,它还实现了对于窗口函数的支持,这仅仅比 MySQL 晚五个月。

接下来,本文将介绍 SQLite 在 2018 年新增加的 SQL 功能,也就是 SQLite 从版本 3.22.0 到 3.26.0 所新增加的 SQL 功能。

具体内容包括:

  • 布尔字面量和判断

  • 窗口函数

  • Filter子句

  • Insert … on conflict (“Upsert”)

  • 重命名列

  • 在Modern-SQL.com上接下来

  • # 布尔变量和判断

    SQLite支持“假”布尔值:它接受Boolean作为类型的名称,但它将其当作整数看待(这一点非常类似于MySQL)。真值true和false分别由数值1和0表示(这一点和C语言一样)。

    从版本3.23.0开始,SQLite将关键字true和false分别用数字1和0表示,并支持is [not] true | false的判断语句。现在,它不再支持关键字unknown。开发者可以使用空值null来代替,因为unknown和null的布尔值是一样的。

    在INSERT和UPDATE语句中,字面量true和false可以大大提高values和set子句的可读性。

    is [not] true | false这个判断语句很有用,它与比较操作的含义不一样:

    我们来比较一下

    WHERE c FALSE

    WHERE c IS NOT FALSE

    在上面的例子中,如果c是null, 那么c false的结果是unknown.

    这是因为WHERE子句只接受结果为true的值,它会过滤掉结果为false或unknown的值。这样,它就会把对应的行从结果中去掉。

    与此相对应,如果c是null,那么,c is not false的判断结果是true。因此,第二个WHERE子句也将包含c是null的行。

    要达到同样的效果,您可以采用的另外一种方法是增加单独处理null值的子句。也就是使用语句:

    WHERE c FALSE OR c IS NULL

    这种形式的语句更长并且有一些冗余语句(c被使用了两次)。长话短说,可以使用is not false判断来替代这个or…is-null的语句。更详细的内容,请参考“Binary Decisions Based on Three-Valued Results”。

    SQLite中对布尔字面量和布尔判断的支持现在和其他开源数据库接近,的差距是SQLite不支持is[not] unknown(你可以使用is [not] null来代替)。有趣的是,这些功能在下面提到的商用产品中还不可用。

    0:只支持true,false.不支持notknown,如果需要,用null代替

    1:不支持is [not] unknown,如果需要,用is [not] null代替

    # 窗口函数

    SQLite 3.25.0引入了窗口函数。如果你知道窗口函数,那么也知道这是一件大事。如果你不了解窗口功能,请你自己学习如何使用。这篇文章不会具体解释窗口函数,但请相信:它是重要的“现代”SQL特性。

    SQLite对over子句的支持与其他数据库非常接近。值得注意的限制是range语句不支持数字或间隔距离(仅支持current row和unbounded preceding|following)。在发布sqlite 3.25.0时,SQL Server和PostgreSQL具有同样的限制。PostgreSQL 11消除了这一限制。

    0:没有变化

    1:Range范围定义不支持datetime类型

    2:Range范围不接受关键字 (只支持unbounded和current row)‍

    SQLite对于窗口函数的支持在业界是领先的。它不支持的功能在其他一些主要产品中也同样不支持(在聚合中语句中的distinct,width_bucket, respect|ignore nulls和from first|last等语句)。

    0:同样没有ORDER BY 语句

    1:不允许负偏移量,nulls的特定处理:lead(, 'IGNORE NULLS'),这里是字符串参数

    2:没有缺省值(第三个参数),不支持respect|ignore nulls语句

    3:不允许负偏移量,不支持ignore nulls语句

    4:不允许负偏移量

    5:不支持respect|ignore nulls语句

    6:不允许负偏移量,不支持respect|ignore nulls语句

    7:nulls的特定处理:first_value(, 1, null, 'IGNORE NULLS') ,这里是字符串参数。

    8:不支持ignore nulls语句

    9:不支持ignore nulls语句和from last语句

    # 过滤语句

    虽然filter语句只是语法糖——你也可以很容易地使用表达式来获得相同的结果——我认为它也是必不可少的语法糖,因为它能使人们更加容易地学习和理解SQL语句。

    看看下面的select子句,您觉得哪一个更容易理解?

    SELECT SUM(revenue) total_revenue , SUM(CASE WHEN product = 1 THEN revenue END ) prod1_revenue ...

    SELECT SUM(revenue) total_revenue , SUM(revenue) FILTER(WHERE product = 1) prod1_revenue ...

    此示例很好地总结了filter子句的作用:它是聚合函数的后缀,可以在进行聚合之前根据特定条件,过滤掉相应的行。pivot技术是filter子句常见的用例。这包括将实体属性值(EAV)模型中的属性转换为表格的列,如果想了解更多的内容,可以参考链接“filter-Selective Aggregates”(https://modern-sql.com/feature/filter)。

    SQLite 从版本3.25.0开始,在使用over子句的聚合函数中支持了filter子句,但是在使用group by子句的聚合函数中还不支持。不幸的是,这意味着您仍然无法在SQLite中使用filter语句来处理上述情况。你必须像以前一样使用case表达式。我真的希望SQLite在这一点上能尽快做到。

    # Insert … on conflict (“Upsert”)

    SQLite 从版本3.24.0开始,引入了“upsert”概念:它是一个insert语句,可以优雅地处理主键和约束的冲突。您可以选择忽略这些冲突(在on conflict语句中什么都不做)或者更新当前行(在on conflict语句中执行更新操作)。

    这是一个特有的SQL扩展,即它不是标准SQL的一部分,因此在下面的矩阵中是灰色的。但是,SQLite遵守与PostgreSQL相同的语法来实现此功能0。该标准提供了对merge语句的支持。

    与PostgreSQL不同,SQLite在以下语句中存在问题。

    INSERT INTO targetSELECT * FROM source ON CONFLICT (id) DO UPDATE SET val = excluded.val

    根据说明文档,这是因为解析器无法判断关键字ON是SELECT语句的连接约束还是upsert子句的开头。你可以通过向查询中添加子句来解决,例如where true。

    INSERT INTO targetSELECT * FROM source WHERE true ON CONFLICT (id) DO UPDATE SET val = excluded.val

    0:同样记录insert、update、delete和merge操作的错误信息 (“DML error logging”)

    1:On conflict语句不能紧挨查询的from语句,如果需要,可以添加 where true语句来分隔。

    # 重命名列

    SQLite引入的另一个特有功能是重命名基准数据库表中的列1。标准的SQL不支持此类功能2。

    SQLite遵循其他产品常用的语法来重命名列:

    ALTER TABLE … RENAME COLUMN … TO

    0:请查阅 sp_rename.

    # 其他消息

    在2018年,SQLite除了在SQL语法上的变化,还有一些应用程序接口(API)的变化。你可以查阅sqlite.com(https://www.sqlite.org/news.html)上的新闻部分来了解更详细的消息。

    脚标:

    0:SQLite通常遵循PostgreSQL语法,Richard Hipp将此称为PostgreSQL会怎么做(WWPD)。

    1:基准数据库表是指用Create table语句创建的数据库表。派生的数据库表(如Select语句返回的查询结果集)中的列名可以通过SELECT语句、FROM语句或WITH语句来进行改变

    2:据我所知,也许可以通过可更新视图或派生的列来模拟该功能。

    相关文章

    SQL数据库触发器语法详解 (sql数据库触发器语法)

    2023-08-06
    数据库
    语法
    触发器

    快速简单的删除Oracle数据库字段方法 (删除oracl数据库字段)

    2023-08-06
    数据库
    字段
    删除

    如何打开社工数据库bak文件 (社工数据库bak怎么打开)

    2023-08-06
    数据库
    打开
    社工

    实现数据库按拼音排序的方法和技巧 (数据库按拼音排序)

    2023-08-06
    数据库
    排序
    按拼音

    探究Sybase数据库的性能和功能特点 (sybase数据库怎么样)

    2023-08-06
    数据库
    性能
    探究

    SQL Server 如何成功建立自己的数据库? (sql server 建立数据库)

    2023-08-06
    数据库
    自己的
    建立

    如何在Oracle中查看数据库触发器? (oracle查看数据库触发器)

    2023-08-06
    数据库
    查看
    触发器

    数据库表数据量千万级,对性能影响有多大? (数据库表千万级数据量多吗)

    2023-08-06
    数据库
    级数
    有多大

    如何使用Oracle按时间导出表数据库? (oracle按时间导出表数据库)

    2023-08-06
    数据库
    导出
    如何使用

    数据库存储:帖子长期保存,信息永不丢失 (帖子存数据库)

    2023-08-06
    数据库
    丢失
    帖子

    小米六数据库:全方位数据保障和优化方案 (小米六数据库)

    2023-08-05
    数据库
    优化
    小米

    简易教程:使用dbe数据库实现数据连接 (dbe数据库 数据连接)

    2023-08-05
    数据
    数据库
    连接

    Oracle实现多个数据库链接的简便方法 (oracle链接多个数据库)

    2023-08-05
    数据库
    多个
    链接

    数据库索引:用哪种方法建立? (数据库索引用什么建的)

    2023-08-05
    索引
    数据库
    哪种

    实现高效缓存同步:Redis数据库技巧大全 (redis 数据库缓存同步)

    2023-08-05
    数据库
    缓存
    同步

    如何利用数据库实现高效的模糊匹配查询? (数据库实现模糊查询)

    2023-08-05
    查询
    数据库
    模糊

    数据库有哪些安装方式和位置? (数据库是装在什么上)

    2023-08-05
    数据库
    位置
    装在

    Lactmed数据库:妈妈们必备的喂养指南 (lactmed 数据库)

    2023-08-05
    数据库
    必备
    喂养

    数据库设计中的主属性定义及作用 (数据库主属性是什么)

    2023-08-05
    数据库
    定义
    属性

    数据库分区操作不当常常造成分区不清的问题 (分区不清数据库)

    2023-08-05
    数据库
    分区
    不清

    相关文章

    Oracle如何使用授予和撤销权限的语法和示例
    Awesome Project: 探索 MatrixOrigin 云原生分布式数据库
    下载丨66页PDF,云和恩墨技术通讯(2024年7月刊)
    社区版oceanbase安装
    Oracle 导出CSV工具-sqluldr2
    ETL数据集成丨快速将MySQL数据迁移至Doris数据库

    发布评论