稀土掘金技术社区 2024年11月09日
前端项目接入sqlite轻量级数据库sql.js指南
index_new5.html
../../../zaker_core/zaker_tpl_static/wap/tpl_guoji1.html

 

本文介绍了如何在前端项目中集成SQLite数据库,并使用sql.js库实现数据库操作。sql.js是一个强大的JavaScript库,它使得SQLite数据库能够在网页浏览器中运行,无需依赖服务器端数据存储。文章详细讲解了两种加载sql.js的方式:npm包安装和CDN引入,并提供了相应的代码示例。此外,文章还探讨了在Node.js环境下(如Electron)使用SQLite数据库的方法,以及如何手动导入导出SQLite文件,并简单介绍了SQLite数据库的持久化缓存方案。

🚀 **sql.js库介绍**: sql.js是一个JavaScript库,允许在浏览器环境中使用SQLite数据库,无需服务器端数据存储,增强了Web应用的数据处理能力。

📚 **两种加载方式**: 文章介绍了两种加载sql.js的方法:使用npm包安装(推荐)和CDN引入,并提供代码示例方便读者理解。

💻 **Node.js环境下的使用**: 文章也讲解了在Node.js环境(例如Electron)下使用SQLite数据库的方法,并提供了手动导入导出SQLite文件的示例。

💾 **SQLite数据持久化**: 文章简要介绍了SQLite数据库的持久化缓存方案,通过将数据库数据存储在浏览器本地存储中来实现数据的持久化。

🌐 **WebAssembly版本**: sql.js通过将SQLite编译成WebAssembly(wasm)来实现高效的数据库操作,支持标准的SQL查询语言。

原创 red润 2024-11-09 09:02 重庆

点击关注公众号,“技术干货”及时达!

点击关注公众号,“技术干货” 及时达!

B站【手把手前端项目接入sqlite数据库sql】 https://www.bilibili.com/video/BV1B2SdYXEEn/?share_source=copy_web&vd_source=60643e0be9c389e9626916661281d724

sql.js 是一个强大的JavaScript库,它使得SQLite数据库能够在网页浏览器中运行。这个开源项目提供了一种方式,让开发者可以在前端环境中实现轻量级的数据库操作,无需依赖服务器端数据存储,极大地增强了Web应用的数据处理能力。通过将SQLite编译成WebAssembly(wasm),sql.js实现了高效的数据库操作,支持标准的SQL查询语言。

sql.js 是 SQLite 的 Webassembly 版,使用上和 SQLite 基本没有区别

如果你需要在浏览器中处理「大量数据」,并且希望使用 SQL 语法来操作这些数据,那么 SQL.js 将是一个不错的选择。

如果您不想在主应用程序线程中运行 CPU 密集型 SQL 查询, 您可以使用更有限的 WebWorker API。

详细api请移步官方文档sql.js sqlite 官网:https://sql.js.org/#/?id=inside-the-browser

sqlite 不会持久化缓存数据,只会存在运行内存中,需要自行导入导出文件。

我们的目标

本指南将sqlite数据集成到网页项目中,并学习相应api操作,

实现案例效果 导入.sqlite文件,执行操作,导出.sqlite文件

本教程使用版本*"sql.js": "^1.11.0"*

项目中加载sql.js

实现的最终效果,浏览器无任何错误,且,会在控制打印{a:1,b:'world'}

您始终可以在 https://github.com/sql-js/sql.js/releases/latest 上找到最新发布的工件。

对于每个版本,您都会在发布资产中找到一个名为的文件。它将包含:sqljs.zip

    sql-wasm.js:Sql.js 的 Web Assembly 版本。缩小并适合生产。使用这个。如果您使用此项,您还需要包含/发货。sql-wasm.wasm

    sql-wasm-debug.js:Web 程序集,Sql.js. Larger 的调试版本,打开了断言。对本地开发有用。如果您使用这个,您将需要包含/发货。sql-wasm-debug.wasm

    sql-asm.js:较旧的 asm.js Sql.js 版本。速度较慢且较大。出于兼容性原因提供。

    sql-asm-memory-growth.js:默认情况下,Asm.js不允许内存增长,因为它速度较慢且会取消优化。如果您使用的是 sql-asm.js 并看到此错误 (),请使用此文件。Cannot enlarge memory arrays

    sql-asm-debug.js:Sql.js的 Debug asm.js 版本。用于本地开发。

    worker.*- 上述库的 Web Worker 版本。更有限的 API。参见 examples/GUI/gui.js 这是一个很好的例子。

有两个版本,一个是在网页中直接加载的版本,一个是electron等桌面端应用使用的版本

1.在网页中加载的版本(本教程的版本),有两种加载方式

    可以使用npm包安装(推荐),使用构建工具「webpack」「vite」

    库下载地址:sql.js - npm (npmjs.com)

     npm i sql.js

    sql.js需要依赖sql-wasm.wasm文件,我们需要添加到自己的目录下面引用

     node_modules     - sql.js         - sql-wasm.wasm将这个文件放在自己的dist目录下面

    新建dist目录/

      dist     - sql-wasm.wasm

    运行下面的代码,没有报错,且控制台打印对应数据

     import initSqlJs  from 'sql.js'; const SQL = await initSqlJs({ // 这里会加载dist/sql-wasm.wasm locateFile: file => `./dist/${file}` });  // Create a database const db = new SQL.Database();  let sqlstr = "CREATE TABLE hello (a int, b char); \ INSERT INTO hello VALUES (0, 'hello'); \ INSERT INTO hello VALUES (1, 'world');"; db.run(sqlstr); // Run the query without returning anything  // Prepare an sql statement const stmt = db.prepare("SELECT * FROM hello WHERE a=:aval AND b=:bval");  // Bind values to the parameters and fetch the results of the query const result = stmt.getAsObject({':aval' : 1, ':bval' : 'world'}); console.log(result); // Will print {a:1, b:'world'} 

    也可以直接在网页中加入(没有使用任何构建工具),需要在 web 静态服务器下访问本文件(推荐 vscode 插件 liveserver)

    库下载地址:sql.js - Libraries - cdnjs - The #1 free and open source CDN built to make life easier for developers

      一种是直接在网页头部引入(不推荐)

      如果cdn出现问题,会导致不可用

       <!DOCTYPE html> <html lang="en">   <head>     <meta charset="UTF-8" />     <link rel="icon" type="image/svg+xml" href="/vite.svg" />     <meta name="viewport" content="width=device-width, initial-scale=1.0" />     <title>Vite App</title>     <script src="https://cdnjs.cloudflare.com/ajax/libs/sql.js/1.11.0/sql-wasm.js" integrity="sha512-tz0jOZaOg9RtWWB6AdxSkINQwIs7S5obj1Dlml9KewZLPTblTWCux5eLtnexBb8kbLUo5crPmjsi8/vI17Vw0w==" crossorigin="anonymous" referrerpolicy="no-referrer"></script>   </head>   <body>     <div id="app"></div>     <script>       config = {       // 从云端加载https://sql.js.org/distsql-wasm.wasm         locateFile: file => `https://sql.js.org/dist/${file}`       };       initSqlJs(config).then(function (SQL) {         //Create the database         const db = new SQL.Database();         // Run a query without reading the results         db.run('CREATE TABLE test (col1, col2);');         // Insert two rows: (1,111) and (2,222)         db.run('INSERT INTO test VALUES (?,?), (?,?)', [1, 111, 2, 222]);          // Prepare a statement         const stmt = db.prepare('SELECT * FROM test WHERE col1 BETWEEN $start AND $end');         stmt.getAsObject({ $start: 1, $end: 1 }); // {col1:1, col2:111}          // Bind new values         stmt.bind({ $start: 1, $end: 2 });         while (stmt.step()) {           //           const row = stmt.getAsObject();           console.log('Here is a row: ' + JSON.stringify(row));         }       });     </script>   </body> </html> 

      一种是将文件下载在自己的文件目录中,然后引入(推荐)

      库下载地址:sql.js - Libraries - cdnjs - The #1 free and open source CDN built to make life easier for developers

      从下载地址下载两个文件,存在dist目录

       dist     - sql-wasm.wasm     - sql-wasm.js
       <!DOCTYPE html> <html lang="en">   <head>     <meta charset="UTF-8" />     <link rel="icon" type="image/svg+xml" href="/vite.svg" />     <meta name="viewport" content="width=device-width, initial-scale=1.0" />     <title>Vite App</title>     <script src="./dist/sql-wasm.js"></script>   </head>   <body>     <div id="app"></div>     <script>       config = {       // 这里请求自己目录下面的.dist/sql-wasm.wasm         locateFile: file => `./dist/${file}`       };       initSqlJs(config).then(function (SQL) {         //Create the database         const db = new SQL.Database();         // Run a query without reading the results         db.run('CREATE TABLE test (col1, col2);');         // Insert two rows: (1,111) and (2,222)         db.run('INSERT INTO test VALUES (?,?), (?,?)', [1, 111, 2, 222]);          // Prepare a statement         const stmt = db.prepare('SELECT * FROM test WHERE col1 BETWEEN $start AND $end');         stmt.getAsObject({ $start: 1, $end: 1 }); // {col1:1, col2:111}          // Bind new values         stmt.bind({ $start: 1, $end: 2 });         while (stmt.step()) {           //           const row = stmt.getAsObject();           console.log('Here is a row: ' + JSON.stringify(row));         }       });     </script>   </body> </html> 

2.在node版本(electron等本机桌面应用程序使用)

库下载地址:sqlite3 - npm (npmjs.com)

 npm install sqlite3

案例

手动导入导出sqlite文件

import initSqlJs from 'sql.js';const importDBFromFile = (event) => {  const file = event.target.files[0];  if (!file) {    return;  }  const reader = new FileReader();  reader.onload = async (e) => {    const data = toBinArray(e.target.result);    db = new SQL.Database(data);    console.log('数据库已导入');    // let sqlstr = "CREATE TABLE hello (a int, b char); \    // INSERT INTO hello VALUES (0, 'hello'); \    // INSERT INTO hello VALUES (1, 'red润'); \    // INSERT INTO hello VALUES (2, 'world');";    // db.run(sqlstr); // Run the query without returning anything    // Prepare an sql statement    const stmt = db.prepare("SELECT * FROM hello WHERE a=:aval");    // Bind values to the parameters and fetch the results of the query    const result = stmt.getAsObject({ ':aval': 0 });    console.log(result); // Will print {a:2, b:'world'}  };  reader.readAsText(file);};const exportDBToFile = () => {  if (!db) {    console.log("请先导入sqlite数据")    return  }  const exportData = db.export();  const blob = new Blob([toBinString(exportData)], { type: 'application/octet-stream' });  const url = URL.createObjectURL(blob);  const a = document.createElement('a');  a.href = url;  a.download = 'database.sqlite';  document.body.appendChild(a);  a.click();  document.body.removeChild(a);  URL.revokeObjectURL(url);};// or if you are in a browser:// const initSqlJs = window.initSqlJs;const toBinArray = (str) => {  var l = str.length,    arr = new Uint8Array(l);  for (var i = 0; i < l; i++) arr[i] = str.charCodeAt(i);  return arr;}const toBinString = (arr) => {  var uarr = new Uint8Array(arr);  var strings = [], chunksize = 0xffff;  // There is a maximum stack size. We cannot call String.fromCharCode with as many arguments as we want  for (var i = 0; i * chunksize < uarr.length; i++) {    strings.push(String.fromCharCode.apply(null, uarr.subarray(i * chunksize, (i + 1) * chunksize)));  }  return strings.join('');}// 在 HTML 中添加文件输入元素const fileInput = document.createElement('input');fileInput.type = 'file';fileInput.accept = '.sqlite';fileInput.addEventListener('change', importDBFromFile);document.body.appendChild(fileInput);// 添加导出按钮const button = document.createElement('button');button.textContent = '导出.sqlite文件';button.addEventListener('click', exportDBToFile);document.body.appendChild(button);const SQL = await initSqlJs({  // Required to load the wasm binary asynchronously. Of course, you can host it wherever you want  // You can omit locateFile completely when running in node  locateFile: file => `./dist/${file}`});let db = null;

持久化缓存

<!doctype html><html><head>   <meta charset="utf8"> <title>Persistent sqlite</title>    <script src="../dist/sql-wasm.js"></script></head><body>    <p>You have seen this page <span id="views">0</span> times.</p> <div>     You have been here on the following dates: <ol id="dates"></ol> </div>    <script>      var baseUrl = '../dist/';       function toBinArray(str) {          var l = str.length,             arr = new Uint8Array(l);            for (var i = 0; i < l; i++) arr[i] = str.charCodeAt(i);          return arr;     }       function toBinString(arr) {         var uarr = new Uint8Array(arr);         var strings = [], chunksize = 0xffff;           // There is a maximum stack size. We cannot call String.fromCharCode with as many arguments as we want          for (var i = 0; i * chunksize < uarr.length; i++) {              strings.push(String.fromCharCode.apply(null, uarr.subarray(i * chunksize, (i + 1) * chunksize)));           }           return strings.join('');        }       // Normally Sql.js tries to load sql-wasm.wasm relative to the page, not relative to the javascript     // doing the loading. So, we help it find the .wasm file with this function.        var config = {          locateFile: filename => `${baseUrl}/${filename}`     }       initSqlJs(config).then(function (SQL) {         var dbstr = window.localStorage.getItem("viewcount.sqlite");            if (dbstr) {                var db = new SQL.Database(toBinArray(dbstr));           } else {                var db = new SQL.Database();                db.run("CREATE TABLE views (date INTEGER PRIMARY KEY)");            }           db.run("INSERT INTO views(date) VALUES (?)", [Date.now()]);         document.getElementById('views').textContent = db.exec("SELECT COUNT(*) FROM views")[0].values[0][0];           var count = 0,              dates = document.getElementById("dates");           db.each("SELECT date FROM views ORDER BY date ASC",             function callback(row) {                    var li = document.createElement("li");                  li.textContent = new Date(row.date);                    dates.appendChild(li);              }, function done() {                    var dbstr = toBinString(db.export());                   window.localStorage.setItem("viewcount.sqlite", dbstr);             }           );      }); </script></body></html>

交互案例

<!doctype html><html><!--Simple Read eval print loop for SQL--><head>   <meta charset="utf8"> <title>SQL REPL</title> <script src="../dist/sql-wasm.js"></script></head><body>    <input type='text' id='input' placeholder="ENTER SOME SQL" size='50'     value="CREATE TABLE test(val);INSERT INTO test VALUES (666); SELECT * FROM test">    <button id='submit'>Execute</button>    <pre id='result'></pre> <pre id='error'></pre>  <script>      //Open a blank database     var db;     initSqlJs({ locateFile: filename => `../dist/${filename}` }).then(function (SQL) {           db = new SQL.Database();        });     document.getElementById('submit').onclick = function () {           var sql = document.getElementById('input').value;           var result = '', error = '';            try { result = db.exec(sql); }          catch (e) { error = e; }            document.getElementById('result').innerHTML = JSON.stringify(result, null, '  ');           document.getElementById('error').innerHTML = error;     };  </script></body>

代码解析

initSqlJs 函数

API 中的根对象是 initSqlJs 函数,它接受一个 SqlJsConfig 参数,并返回一个 SqlJs 对象

SqlJs 对象

initSqlJs返回主 sql.js 对象 SqlJs 模块,其中包含:

常用操作

详细api请移步官方文档sql.js

创建数据库/导入数据

// 创建一个新的数据库实例const db = new SQL.Database();// 创建并加载数据(见案例章节)var db = new SQL.Database(toBinArray(dbstr));

查询

// 执行一个 INSERT 语句db.run("INSERT INTO tasks (name, priority) VALUES ('Buy groceries', 'high')");// 执行一个 SELECT 语句const result = db.exec("SELECT * FROM tasks WHERE priority='high'");// 输出结果console.log(result);

导出

// 导出数据库const databaseBlob = db.export();

可能遇到的问题

1. 配置 Vite 以包括 .db 文件

vite.config.js 中,您可以添加以下配置:

import { defineConfig } from 'vite';export default defineConfig({  assetsInclude: ['**/*.db'],});

2. 确保文件路径正确

确保您在项目中引用 .db 文件的路径是正确的。例如:

const dbFilePath = './path/to/your.db'; // 确保路径正确

3. 处理 .db 文件

在代码中,确保您正确加载和处理 .db 文件。例如,使用 fetch 来获取文件内容:

const response = await fetch(dbFilePath);// 转换成bufferconst data = await response.arrayBuffer();const db = new SQL.Database(new Uint8Array(data)); // 从文件加载数据库

完结

sqlite确实好用,如无「必要」,勿「增实体」

点击关注公众号,“技术干货” 及时达!

阅读原文

跳转微信打开

Fish AI Reader

Fish AI Reader

AI辅助创作,多种专业模板,深度分析,高质量内容生成。从观点提取到深度思考,FishAI为您提供全方位的创作支持。新版本引入自定义参数,让您的创作更加个性化和精准。

FishAI

FishAI

鱼阅,AI 时代的下一个智能信息助手,助你摆脱信息焦虑

联系邮箱 441953276@qq.com

相关标签

SQLite sql.js 前端数据库 WebAssembly JavaScript
相关文章