小巧、快速、可靠。
任选三项。

从 SQLite 3.5.9 迁移到 3.6.0

SQLite 版本 3.6.0 (2008-07-16) 包含许多更改。按照 SQLite 项目的惯例,大多数更改都完全向后兼容。但是,3.6.0 版本中的某些更改不兼容,可能需要修改应用程序代码和/或 makefile。本文档简要介绍了 SQLite 3.6.0 中的更改,特别关注不兼容的更改。

要点

1.0 不兼容更改

首先介绍不兼容的更改,因为它们对维护人员和程序员来说是最重要的。

1.1 不兼容更改概述

  1. sqlite3_vfs 对象的更改

    1. xAccess 方法的签名已修改,以返回一个 错误代码 并将其输出存储到一个参数指向的整数中,而不是直接返回输出。此更改允许 xAccess() 方法报告失败。与此签名更改相关,已添加一个新的扩展错误代码 SQLITE_IOERR_ACCESS

    2. xGetTempname 方法已从 sqlite3_vfs 中删除。取而代之的是,xOpen 方法得到了增强,可以在 filename 参数为 NULL 时打开它自己发明的临时文件。

    3. sqlite3_vfs 中添加了 xGetLastError() 方法,用于将特定于文件系统的错误消息和错误代码返回给 SQLite。

  2. sqlite3_io_methods 上的 xCheckReservedLock 方法的签名已修改,因此它返回一个 错误代码 并将其布尔结果存储到一个参数指向的整数中。与此更改相关,已添加一个新的扩展错误代码 SQLITE_IOERR_CHECKRESERVEDLOCK

  3. 当 SQLite 移植到新的操作系统(除了 Unix、Windows 和 OS/2,这些操作系统与核心一起提供了端口)时,必须提供两个新函数 sqlite3_os_init()sqlite3_os_end() 作为端口的一部分。

  4. IN 和 NOT IN 运算符处理其右侧表达式中的 NULL 值的方式已符合 SQL 标准以及其他 SQL 数据库引擎。

  5. 在某些情况下,SELECT 语句的结果集的列名已被调整,以更像其他 SQL 数据库引擎。

  6. 编译时选项的更改

    1. 不再识别 SQLITE_MUTEX_APPDEF 编译时参数。作为替代,可以使用 sqlite3_config() 以及 SQLITE_CONFIG_MUTEX 运算符和 sqlite3_mutex_methods 对象在运行时创建替代的 互斥体实现

    2. 编译时选项 OS_UNIX、OS_WIN、OS_OS2、OS_OTHER 和 TEMP_STORE 已被重命名,包括 "SQLITE_" 前缀,以帮助避免与应用程序软件的命名空间冲突。这些选项的新名称分别是:SQLITE_OS_UNIX、SQLITE_OS_WIN、SQLITE_OS_OS2、SQLITE_OS_OTHER 和 SQLITE_TEMP_STORE

1.2 对 VFS 层的更改

SQLite 版本 3.5.0 引入了一个 新的 OS 接口层,它提供了对底层操作系统的抽象。这是一个重要的创新,并已被证明有助于移植和维护 SQLite。但是,开发人员在 3.5.0 版本中引入的原始 "虚拟文件系统" 设计中发现了一些小缺陷,因此 SQLite 3.6.0 包含一些小的不兼容更改来解决这些缺陷。

要点:SQLite 3.6.0 版本操作系统接口中的不兼容更改只影响很少的应用程序,这些应用程序使用 虚拟文件系统 接口或提供应用程序定义的 互斥体实现 或者使用其他不常用的编译时选项。SQLite 版本 3.6.0 引入的更改对使用 Unix、Windows 和 OS/2 的内置接口以及使用标准构建配置的大多数 SQLite 应用程序将没有影响。

1.3 IN 运算符处理 NULL 的方式的更改

所有 SQLite 版本,包括 3.5.9 版本,都对 IN 和 NOT IN 运算符右侧的 NULL 值处理不当。具体来说,SQLite 以前忽略了 IN 和 NOT IN 右侧的 NULL。

假设我们有一个名为 X1 的表,其定义如下

  CREATE TABLE x1(x INTEGER);
  INSERT INTO x1 VALUES(1);
  INSERT INTO x1 VALUES(2);
  INSERT INTO x1 VALUES(NULL);

在上面的 X1 定义下,以下表达式在 SQLite 中以前被评估为 FALSE,但正确答案实际上是 NULL

  3 IN (1,2,NULL)
  3 IN (SELECT * FROM x1)

同样,以下表达式在 SQLite 中以前被评估为 TRUE,但实际上 NULL 也是这里的正确答案

  3 NOT IN (1,2,NULL)
  3 NOT IN (SELECT * FROM x1)

根据 SQL:1999 标准,SQLite 的历史行为是错误的,它与 MySQL 和 PostgreSQL 的行为不一致。3.6.0 版本更改了 IN 和 NOT IN 运算符的行为,以符合标准并与其他 SQL 数据库引擎给出相同的结果。

要点:对 IN 和 NOT IN 运算符处理 NULL 值方式的更改从技术上来说是一个错误修复,而不是设计更改。但是,维护人员应检查以确保应用程序在升级到 3.6.0 版本之前不依赖于旧的、有错误的行为。

1.4 对列命名规则的更改

连接子查询报告的列名已略微修改,以更像其他数据库引擎。考虑以下查询

  CREATE TABLE t1(a);
  CREATE TABLE t2(x);
  SELECT * FROM (SELECT t1.a FROM t1 JOIN t2 ORDER BY t2.x LIMIT 1) ORDER BY 1;

在 3.5.9 版本中,上面的查询将返回一个名为 "t1.a" 的单个列。在 3.6.0 版本中,列名只是 "a"。

SQLite 从未对 SELECT 语句结果集中的列名称做出任何承诺,除非该列包含 AS 子句。因此,对列名的更改从技术上来说不是不兼容的。SQLite 只是从一种未定义的行为变为另一种未定义的行为。然而,许多应用程序依赖于 SQLite 未指定的列命名行为,因此此更改在不兼容更改子标题下进行讨论。

1.5 对编译时选项的更改

SQLite 的编译时选项由 C 预处理器宏控制。SQLite 版本 3.6.0 更改了其中一些宏的名称,以便所有特定于 SQLite 的 C 预处理器宏都以 "SQLITE_" 前缀开头。这样做是为了降低与其他软件模块发生名称冲突的风险。

要点:对编译时选项的更改可能会影响对 SQLite 进行自定义构建的项目的 makefile。这些更改对应用程序代码应该没有影响,对于大多数使用 SQLite 的标准、默认构建的项目来说也是如此。

2.0 完全向后兼容的增强功能

除了上面列出的不兼容更改之外,SQLite 版本 3.6.0 还添加了以下向后兼容的更改和增强功能

  1. 新的 sqlite3_config() 接口允许应用程序在运行时自定义 SQLite 的行为。可以使用 sqlite3_config() 进行的自定义包括以下内容

    1. 使用 SQLITE_CONFIG_MUTEX 动词和 sqlite3_mutex_methods 对象指定替代的互斥体实现。

    2. 使用 SQLITE_CONFIG_MALLOC 动词和 sqlite3_mem_methods 对象指定替代的 malloc 实现。

    3. 使用 SQLITE_CONFIG_SINGLETHREADSQLITE_CONFIG_MULTITHREADSQLITE_CONFIG_SERIALIZED 部分或完全禁用互斥体的使用。

  2. 一个新的标志 SQLITE_OPEN_NOMUTEX 可用于 sqlite3_open_v2() 接口。

  3. 新的 sqlite3_status() 接口允许应用程序在运行时查询 SQLite 的性能状态。

  4. sqlite3_memory_used()sqlite3_memory_highwater() 接口已弃用。等效的功能现在可通过 sqlite3_status() 获得。

  5. sqlite3_initialize() 接口可以被调用以显式初始化 SQLite 子系统。在调用某些接口时,sqlite3_initialize() 接口会自动调用,因此不需要使用 sqlite3_initialize(),但建议使用。

  6. sqlite3_shutdown() 接口会导致 SQLite 释放可能由 sqlite3_initialize() 分配的任何系统资源(内存分配、互斥体、打开的文件句柄)。

  7. sqlite3_next_stmt() 接口允许应用程序发现与 数据库连接 关联的所有 预处理语句

  8. 添加了 page_count PRAGMA,用于返回底层数据库文件的大小(以页为单位)。

  9. 添加了一个新的 R*Tree 索引扩展

此页面最后修改于 2022-01-08 05:02:57 UTC