前端项目接入sqlite轻量级数据库sql.js指南
前端项目接入sqlite轻量级数据库sql.js指南
引言
sql.js 是一个强大的JavaScript库,它使得SQLite数据库能够在网页浏览器中运行。这个开源项目提供了一种方式,让开发者可以在前端环境中实现轻量级的数据库操作,无需依赖服务器端数据存储,极大地增强了Web应用的数据处理能力。通过将SQLite编译成WebAssembly(wasm),sql.js实现了高效的数据库操作,支持标准的SQL查询语言。
如果你需要在浏览器中处理大量数据,并且希望使用 SQL 语法来操作这些数据,那么 SQL.js 将是一个不错的选择。
如果您不想在主应用程序线程中运行 CPU 密集型 SQL 查询, 您可以使用更有限的 WebWorker API。
详细api请移步官方文档sql.js sqlite 官网:https://sql.js.org/#/?id=inside-the-browser
sqlite 不会持久化缓存数据,只会存在运行内存中,需要自行导入导出文件。
我们的目标
本指南将sqlite数据集成到网页项目中,并学习相应api操作,
实现案例效果
本教程使用版本*“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.wasmsql-wasm-debug.js:Web 程序集,Sql.js. Larger 的调试版本,打开了断言。对本地开发有用。如果您使用这个,您将需要包含/发货。sql-wasm-debug.wasmsql-asm.js:较旧的 asm.js Sql.js 版本。速度较慢且较大。出于兼容性原因提供。sql-asm-memory-growth.js:默认情况下,Asm.js不允许内存增长,因为它速度较慢且会取消优化。如果您使用的是 sql-asm.js 并看到此错误 (),请使用此文件。Cannot enlarge memory arrayssql-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.jssql.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.wasmlocateFile: file => `https://sql.js.org/dist/${file}`};initSqlJs(config).then(function (SQL) {//Create the databaseconst db = new SQL.Database();// Run a query without reading the resultsdb.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 statementconst stmt = db.prepare('SELECT * FROM test WHERE col1 BETWEEN $start AND $end');stmt.getAsObject({ $start: 1, $end: 1 }); // {col1:1, col2:111} // Bind new valuesstmt.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.wasmlocateFile: file => `./dist/${file}`};initSqlJs(config).then(function (SQL) {//Create the databaseconst db = new SQL.Database();// Run a query without reading the resultsdb.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 statementconst stmt = db.prepare('SELECT * FROM test WHERE col1 BETWEEN $start AND $end');stmt.getAsObject({ $start: 1, $end: 1 }); // {col1:1, col2:111} // Bind new valuesstmt.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
案例
持久化缓存
<!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 wantfor (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 databasevar 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 模块,其中包含:
-
Database
-
构造函数
-
const db = new SQL.Database(); -
let data = const db = new SQL.Database(data);
-
-
close()- 关闭数据库
-
注册自定义aggregate
-
db.create_aggregate("js_sum", {init: () => 0,step: (state, value) => state + value,finalize: state => state});db.exec("SELECT js_sum(column1) FROM (VALUES (1), (2))"); // = 3
-
-
创建函数
-
db.create_function("addOne", function (x) {return x+1;})db.exec("SELECT addOne(1)") // = 2
-
-
执行 sql 语句,并为每行 result 调用回调。
-
db.each("SELECT name,age FROM users WHERE age >= $majority", {$majority:18},function (row){console.log(row.name + " is a grown-up.")});
-
-
执行sql
-
var db = new SQL.Database(); var res = db.exec("DROP TABLE IF EXISTS test;\n"+ "CREATE TABLE test (id INTEGER, age INTEGER, name TEXT);"+ "INSERT INTO test VALUES ($id1, :age1, @name1);"+ "INSERT INTO test VALUES ($id2, :age2, @name2);"+ "SELECT id FROM test;"+ "SELECT age,name FROM test WHERE id=$id1",{"$id1": 1, ":age1": 1, "@name1": "Ling","$id2": 2, ":age2": 18, "@name2": "Paul"} );
-
-
将数据库的内容导出到二进制数组。此操作将关闭并重新打开数据库,这将导致程序设置回其默认值。
-
let res = db.export() console.log(res)
-
-
准备sql
-
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 valuesstmt.bind({ $start: 1, $end: 2 });while (stmt.step()) {//const row = stmt.getAsObject();console.log('Here is a row: ' + JSON.stringify(row));}
-
-
执行sql
-
db.run("INSERT INTO test VALUES (:age, :name)",{ ':age' : 18, ':name' : 'John' });
-
-
-
Statement
Statement 类用于准备好的语句。
var stmt = db.prepare("UPDATE test SET a=@newval WHERE id BETWEEN $mini AND $maxi");stmt.bind({$mini:10, $maxi:20, '@newval':5});
常用操作
详细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 中,您可以添加以下配置:
javascriptCopy Code
import { defineConfig } from 'vite';export default defineConfig({assetsInclude: ['**/*.db'],
});
2. 确保文件路径正确
确保您在项目中引用 .db 文件的路径是正确的。例如:
const dbFilePath = './path/to/your.db'; // 确保路径正确
3. 处理 .db 文件
在代码中,确保您正确加载和处理 .db 文件。例如,使用 fetch 来获取文件内容:
javascriptCopy Code
const response = await fetch(dbFilePath);
// 转换成buffer
const data = await response.arrayBuffer();
const db = new SQL.Database(new Uint8Array(data)); // 从文件加载数据库
完结
sqlite确实好用,如无必要,勿增实体
相关文章:
前端项目接入sqlite轻量级数据库sql.js指南
前端项目接入sqlite轻量级数据库sql.js指南 引言 sql.js 是一个强大的JavaScript库,它使得SQLite数据库能够在网页浏览器中运行。这个开源项目提供了一种方式,让开发者可以在前端环境中实现轻量级的数据库操作,无需依赖服务器端数据存储&…...
模拟退火算法(Simulated Annealing)详细解读
模拟退火算法(Simulated Annealing) 是一种随机优化算法,受到物理学中金属退火过程的启发。它用于寻找全局最优解,特别适合解决组合优化问题。模拟退火算法通过模拟物质在加热和冷却过程中粒子位置的变化,逐渐寻找系统…...
(二十一)、Docker 部署 Minikube 使用可视化管理工具 Kuboard
文章目录 1、介绍docker 运行 minikube 集群节点(kube-apiserver )无法被直接访问的问题Kuboard 需要访问到 k8s 集群的kube-apiserver 2、安装 Kuboard2.1、k8s 集群节点可以被外部直接访问的情况2.1.1、下载镜像2.1.2、运行 deployment.yml2.1.3、访问…...
代码编辑组件
代码编辑组件 文章说明核心代码运行演示源码下载 文章说明 拖了很久,总算是自己写了一个简单的代码编辑组件,虽然还有不少的bug,真的很难写,在写的过程中感觉自己的前端技术根本不够用,好像总是方案不够好;…...
裴蜀定理与欧几里得算法——蓝桥杯真题中的应用
目录 裴蜀定理(Bzouts Theorem)1、定义2、推论3、欧几里得算法4、多个整数的裴蜀定理扩展 真题挑战解题思路代码实现与详细注释代码解析 裴蜀定理(Bzout’s Theorem) 1、定义 对于任意两个整数 a 和 b ,如果它们的最…...
冯诺依曼架构及CPU相关概念
一. 操作系统的概念 1. 概念 操作系统(Operating System). 首先, 所有的计算机都是由软件和硬件构成的. 而操作系统就是许许多多软件中的一种软件, 操作系统可以看作是由两部分组成: 操作系统内核系统级应用程序. 2. 作用 (1) 管理硬件设备, 调度和协调各个硬件之间的工作.…...
智能管线巡检系统:强化巡检质量,确保安全高效运维
线路巡检质量的监控是确保线路安全、稳定运行的重要环节。为了有效监控巡检质量,采用管线巡检系统是一种高效、科学的手段。以下是对如何通过管线巡检系统实现线路巡检质量监控的详细分析: 一、巡检速度监控 管线巡检系统能够实时监控巡检人员的巡检速度…...
React写关键字高亮的三个方案
1.js正则replaceAlldangerouslySetInnerHTML{{ __html: xxx }}危险属性 步骤最简单,但是是危险属性,不推荐使用,项目中实在没有头绪,可以使用它应急 通过useMemo计算得到新的状态值,赋值给dangerouslySetInnerHTML属性的__html 关键代码: const [state1, setState1] useSt…...
重塑在线软件开发新纪元:集成高效安全特性,深度解析与评估会员与促销管理系统的系统架构设计
案例 阅读以下关于软件架构设计与评估的叙述,回答问题1和问题2。 【题目】 某电子商务公司拟升级其会员与促销管理系统,向用户提供个性化服务,提高用户的粘性。在项目立项之初,公司领导层一致认为本次升级的主要目标是提升会员管…...
多层感知机的从零实现与softmax的从零实现(真·0000零基础)
今天再读zh.d2l书(4.2. 多层感知机的从零开始实现 — 动手学深度学习 2.0.0 documentation), 看了关于多层感知机的从零实现与softmax的从零实现 目录 mlp从零实现, 点击“paddle”的代码 点击“torch”的代码 训练 参数解…...
【Rust练习】18.特征 Trait
练习题来自:https://practice-zh.course.rs/generics-traits/traits.html 1 // 完成两个 impl 语句块 // 不要修改 main 中的代码 trait Hello {fn say_hi(&self) -> String {String::from("hi")}fn say_something(&self) -> String; }str…...
【自动化测试之oracle数据库】MacOs如何安装oracle- client
操作系统为Mac OS,本地在pycharm上跑自动化脚本时,因为有操作oracle数据库的部分,所以需要安装oracle数据库的客户端,并install cx_oracle,本文主要介绍如何在macOS上完成安装,并在python自动化测试代码中配置…...
Spring MVC的MultipartFile
定义 MultipartFile接口是Spring MVC中用来处理上传文件的接口,它提供了访问上传文件内容、文件名称、文件大小等信息的方法。 源码: package org.springframework.web.multipart;import java.io.File; import java.io.IOException; import java.io.I…...
●Leetcode| 242.有效的字母异位词 ● 349. 两个数组的交集 ● 202. 快乐数● 1. 两数之和
242,该题目中数组范围比较短,可以数组使用并不会占太多的空间,利用数组的映射,查找到自己所需要的字符 class Solution { public:bool isAnagram(string s, string t) {int record[26] {0};for(int i0;i<s.size();i){record[s[i] - a];/…...
关于算法的时间复杂度和空间复杂度的分析
由于最近开始准备蓝桥杯(python组),开始对编程基础进行一些复习,当我发现蓝桥对大多数题目程序运行时间及大小有要求时,我知道我不得不考虑性能问题,而不是能跑就行🤓 写下这篇文章希望对其他同志有帮助吧 什么是算法…...
深入浅出 C++ STL:解锁高效编程的秘密武器
引言 C 标准模板库(STL)是现代 C 的核心部分之一,为开发者提供了丰富的预定义数据结构和算法,极大地提升了编程效率和代码的可读性。理解和掌握 STL 对于 C 开发者来说至关重要。以下是对 STL 的详细介绍,涵盖其基础知…...
2024年1024程序人生总结
2024-1024 0.大环境0.1.经济0.2.战争 1.我的程序人生1.1.游戏 2.节日祝福 0.大环境 今年的1024最大的感触就是没有节日氛围,往年公司还会准备节日礼物,今年没有,由此可见大环境有多么糟糕。 除此之外,就是到公司应聘的程序员越来…...
【p2p、分布式,区块链笔记 分布式容错算法】: 拜占庭将军问题+实用拜占庭容错算法PBFT
papercodehttps://pmg.csail.mit.edu/papers/osdi99.pdfhttps://github.com/luckydonald/pbft 其他相关实现:This is an implementation of the Pracltical Byzantine Fault Tolerance protocol using PythonAn implementation of the PBFT consensus algorithm us…...
鸿蒙NEXT开发-应用数据持久化之用户首选项(基于最新api12稳定版)
注意:博主有个鸿蒙专栏,里面从上到下有关于鸿蒙next的教学文档,大家感兴趣可以学习下 如果大家觉得博主文章写的好的话,可以点下关注,博主会一直更新鸿蒙next相关知识 专栏地址: https://blog.csdn.net/qq_56760790/…...
人工智能_神经网络103_感知机_感知机工作原理_感知机具备学习能力_在学习过程中自我调整权重_优化效果_多元线性回归_逻辑回归---人工智能工作笔记0228
由于之前一直对神经网络不是特别清楚,尤其是对神经网络中的一些具体的概念,包括循环,神经网络卷积神经网络以及他们具体的作用,都是应用于什么方向不是特别清楚,所以现在我们来做教程来具体明确一下。 当然在机器学习之后还有深度学习,然后在深度学习中对各种神经网络的…...
装饰模式(Decorator Pattern)重构java邮件发奖系统实战
前言 现在我们有个如下的需求,设计一个邮件发奖的小系统, 需求 1.数据验证 → 2. 敏感信息加密 → 3. 日志记录 → 4. 实际发送邮件 装饰器模式(Decorator Pattern)允许向一个现有的对象添加新的功能,同时又不改变其…...
CVPR 2025 MIMO: 支持视觉指代和像素grounding 的医学视觉语言模型
CVPR 2025 | MIMO:支持视觉指代和像素对齐的医学视觉语言模型 论文信息 标题:MIMO: A medical vision language model with visual referring multimodal input and pixel grounding multimodal output作者:Yanyuan Chen, Dexuan Xu, Yu Hu…...
在鸿蒙HarmonyOS 5中实现抖音风格的点赞功能
下面我将详细介绍如何使用HarmonyOS SDK在HarmonyOS 5中实现类似抖音的点赞功能,包括动画效果、数据同步和交互优化。 1. 基础点赞功能实现 1.1 创建数据模型 // VideoModel.ets export class VideoModel {id: string "";title: string ""…...
【解密LSTM、GRU如何解决传统RNN梯度消失问题】
解密LSTM与GRU:如何让RNN变得更聪明? 在深度学习的世界里,循环神经网络(RNN)以其卓越的序列数据处理能力广泛应用于自然语言处理、时间序列预测等领域。然而,传统RNN存在的一个严重问题——梯度消失&#…...
JVM垃圾回收机制全解析
Java虚拟机(JVM)中的垃圾收集器(Garbage Collector,简称GC)是用于自动管理内存的机制。它负责识别和清除不再被程序使用的对象,从而释放内存空间,避免内存泄漏和内存溢出等问题。垃圾收集器在Ja…...
学校招生小程序源码介绍
基于ThinkPHPFastAdminUniApp开发的学校招生小程序源码,专为学校招生场景量身打造,功能实用且操作便捷。 从技术架构来看,ThinkPHP提供稳定可靠的后台服务,FastAdmin加速开发流程,UniApp则保障小程序在多端有良好的兼…...
【Go语言基础【12】】指针:声明、取地址、解引用
文章目录 零、概述:指针 vs. 引用(类比其他语言)一、指针基础概念二、指针声明与初始化三、指针操作符1. &:取地址(拿到内存地址)2. *:解引用(拿到值) 四、空指针&am…...
【C++特殊工具与技术】优化内存分配(一):C++中的内存分配
目录 一、C 内存的基本概念 1.1 内存的物理与逻辑结构 1.2 C 程序的内存区域划分 二、栈内存分配 2.1 栈内存的特点 2.2 栈内存分配示例 三、堆内存分配 3.1 new和delete操作符 4.2 内存泄漏与悬空指针问题 4.3 new和delete的重载 四、智能指针…...
LLMs 系列实操科普(1)
写在前面: 本期内容我们继续 Andrej Karpathy 的《How I use LLMs》讲座内容,原视频时长 ~130 分钟,以实操演示主流的一些 LLMs 的使用,由于涉及到实操,实际上并不适合以文字整理,但还是决定尽量整理一份笔…...
苹果AI眼镜:从“工具”到“社交姿态”的范式革命——重新定义AI交互入口的未来机会
在2025年的AI硬件浪潮中,苹果AI眼镜(Apple Glasses)正在引发一场关于“人机交互形态”的深度思考。它并非简单地替代AirPods或Apple Watch,而是开辟了一个全新的、日常可接受的AI入口。其核心价值不在于功能的堆叠,而在于如何通过形态设计打破社交壁垒,成为用户“全天佩戴…...
