从 Web SQL 到 SQLite Wasm:数据库迁移指南

借助由源私有文件系统支持的 SQLite Wasm,您可以使用通用方式替代已弃用的 Web SQL 数据库技术。本文将介绍如何将数据从 Web SQL 迁移到 SQLite Wasm。

所需背景

弃用和移除 Web SQL 一文中宣布了弃用 Web SQL 数据库技术。虽然这项技术本身可能会废弃,但该技术所涉及的用例却不是,因此在后续博文 SQLite Wasm 在由源私有文件系统支持的浏览器中概述了一组基于 SQLite 数据库、编译为 Web Assembly (Wasm) 并由原始私有文件系统提供支持的技术。最后,本文介绍了如何将数据库从 Web SQL 迁移到 SQLite Wasm。

迁移数据库

以下四个步骤演示了将 Web SQL 数据库迁移到 SQLite Wasm(使用由原始私有文件系统提供支持的 SQLite 数据库)的概念性思路。您可以将其用作基础,根据您的 Web SQL 迁移需求自定义您的代码。

要迁移的 Web SQL 数据库

本迁移指南的基准假设您有一个(或多个)现有 Web SQL 数据库,用于存储与您的应用相关的数据。在下面的屏幕截图中,您可以看到一个名为 mydatabase 的示例数据库,其中包含一个将情绪与严重程度映射到的暴雨表。借助 Chrome 开发者工具,您可以查看 Web SQL 数据库以进行调试,如以下屏幕截图所示。

在 Chrome 的开发者工具中检查的 Web SQL 数据库。该数据库称为 mydatabase,它托管了一个包含以下三列的表:行 ID、情绪和严重程度。有三行示例数据。

将 Web SQL 数据库转换为 SQL 语句

要以对用户透明的方式迁移数据(即不要求用户自行执行任何迁移步骤),需要将数据库中的数据片段转换回最初创建它们的原始 SQL 语句。之前曾出现过这一挑战,本文中使用的迁移脚本 mywebsqldump.js 基于一个名为 websqldump.js 的社区库,并进行了一些细微的调整。以下代码示例展示了将 Web SQL 数据库 mydatabase 转换为一组 SQL 语句所需的代码。

websqldump.export({
  database: 'mydatabase',
  version: '1.0',
  success: function(sql) {
    // The SQL statements.
  },
  error: function(err) {
    // Handle the error.
  }
});

运行此代码会生成下面的 SQL 语句字符串。

CREATE TABLE IF NOT EXISTS rainstorms (mood text, severity int);
INSERT INTO rainstorms(mood,severity) VALUES ('somber','6');
INSERT INTO rainstorms(mood,severity) VALUES ('rainy','8');
INSERT INTO rainstorms(mood,severity) VALUES ('stormy','2');

将数据导入 SQLite Wasm

剩下的任务就是在 SQLite Wasm 上下文中执行这些 SQL 命令。如需了解有关设置 SQLite Wasm up 的所有详细信息,请参阅 SQLite Wasm 在由源私有文件系统支持的浏览器中这篇文章,但要点如下。请注意,此代码需要在工作器(由库自动为您创建)中运行,并正确设置所需的 HTTP 标头。您可以从 npm 安装 @sqlite.org/sqlite-wasm 软件包。

import { sqlite3Worker1Promiser } from '@sqlite.org/sqlite-wasm';

(async () => {
  try {
    const promiser = await new Promise((resolve) => {
      const _promiser = sqlite3Worker1Promiser({
        onready: () => {
          resolve(_promiser);
        },
      });
    });

    let response;

    response = await promiser('open', {
      filename: 'file:mydatabase.db?vfs=opfs',
    });
    const { dbId } = response;

    const sql = `
      CREATE TABLE IF NOT EXISTS rainstorms (mood text, severity int);
      INSERT INTO rainstorms(mood,severity) VALUES ('somber','6');
      INSERT INTO rainstorms(mood,severity) VALUES ('rainy','8');
      INSERT INTO rainstorms(mood,severity) VALUES ('stormy','2');`
    await promiser('exec', { dbId, sql });

    await promiser('close', { dbId });
  } catch (err) {
    if (!(err instanceof Error)) {
      err = new Error(err.result.message);
    }
    console.error(err.name, err.message);
  }
})();

运行此代码后,使用 OPFS Explorer Chrome 开发者工具扩展程序检查导入的数据库文件。现在有两个文件,一个包含实际数据库,另一个包含日记信息。请注意,这两个文件位于来源专用文件系统中,因此需要使用 OPFS Explorer 扩展程序才能查看它们。

使用 OPFS Explorer Chrome 开发者工具检查源私有文件系统。有两个文件,一个名为 mydatabase.db,另一个名为 mydatabase.db-journal。

如需实际验证导入的数据是否与初始 Web SQL 数据相同,请点击文件 mydatabase.db,OPFS Explorer 扩展程序会显示 Save File 对话框,让您可以将文件保存到用户可见的文件系统中。保存数据库文件后,使用 SQLite 查看器应用探索数据。Project Fugu API Showcase 提供了多个可在浏览器中使用 SQLite 的应用。例如,Sqlime - SQLite Playground 可让您从硬盘打开 SQLite 数据库文件,并对数据库运行查询。如下面的屏幕截图所示,Ramino 表已正确导入到 SQLite 中。

在 Sqlime SQLite Playground 工具中探索 mydatabase.db 文件。该应用显示时运行了 SQL 查询 select star from rainstubs limit 10,结果生成来自 Web SQL 初始样本数据的三行。

释放 Web SQL 存储空间

虽然无法删除 Web SQL 数据库(或许令人惊讶),但您仍然可以在将数据迁移到 SQLite Wasm 后,通过删除现已过时的 Web SQL 表来释放一些存储空间。要列出 Web SQL 数据库中的所有表并使用 JavaScript 删除这些表,请使用如以下代码段所示的代码:

const dropAllTables = () => {
  try {
    db.transaction(function (tx) {
      tx.executeSql(
        "SELECT name FROM sqlite_master WHERE type='table' AND name !='__WebKitDatabaseInfoTable__'",
        [],
        function (tx, result) {
          const len = result.rows.length;
          const tableNames = [];
          for (let i = 0; i < len; i++) {
            const tableName = result.rows.item(i).name;
            tableNames.push(`'${tableName}'`);
            db.transaction(function (tx) {
              tx.executeSql('DROP TABLE ' + tableName);
            });
          }
          console.log(`Dropped table${tableNames.length > 1 ? 's' : ''}: ${tableNames.join(', ')}.`);
        }
      );
    });
  } catch (err) {
    console.error(err.name, err.message);
  }
};

使用迁移后的数据

迁移数据后,请按照此使用入门代码示例中的说明处理数据。如需了解详情,请参阅 SQLite Wasm API 参考文档。再次提醒您,如果您使用源私有文件系统作为存储后端,则需要从工作器访问 SQLite Wasm。

开始测试

通过此演示,您可以使用示例数据填充 Web SQL 数据库,然后将 Web SQL 数据转储为 SQL 语句,然后将这些语句导入到由源私有文件系统支持的 SQLite Wasm 中。最后,您可以通过删除过时的 Web SQL 数据来释放存储空间。如需了解完整实现,包括经过修补的 mywebsqldump.js 文件,请查看源代码

web-sql-to-sqlite-wasm.glitch.me 上的演示版应用。

总结

您可以以对用户透明的方式将 Web SQL 数据库迁移到由源专用文件系统支持的 SQLite Wasm。他们不会注意到,他们的数据现在托管在 SQLite 数据库中的原始私有文件系统中,不再位于 Web SQL 中。总体而言,对于希望确保应用长期稳定性和可伸缩性的 Web 开发者来说,从 Web SQL 迁移到 SQLite 是一个必要步骤。虽然此过程可能需要一些初始工作,但更强大、更灵活,最重要的是,可以满足未来需求的数据库解决方案的优势在于它值得投资。