百度360必应搜狗淘宝本站头条
当前位置:网站首页 > IT知识 > 正文

SQL.js 开源:在浏览器中运行 SQLite 数据库

liuian 2024-12-07 14:59 34 浏览

家好,很高兴又见面了,我是"高级前端?进阶?",由我带着大家一起关注前端前沿、深入前端底层技术,大家一起进步,也欢迎大家关注、点赞、收藏、转发,您的支持是我不断创作的动力。

1.什么是 sql.js

sql.js is a port of SQLite to Webassembly, by compiling the SQLite C code with Emscripten. It uses a virtual database file stored in memory, and thus doesn't persist the changes made to the database. However, it allows you to import any existing sqlite file, and to export the created database as a JavaScript typed array.

sql.js 是 SQLite 到 WebAssembly 的端口,通过使用 Emscripten 编译 SQLite C 代码。

sql.js 允许开发者创建关系数据库并完全在浏览器中查询,而且使用存储在内存中的虚拟数据库文件,因此不会保留对数据库所做的更改。 但是,其允许开发者导入任何现有的 sqlite 文件,并将创建的数据库导出为 JavaScript 类型数组。

sql.js 可以像任何传统的 JavaScript 库一样使用,因此如果正在使用 JavaScript 构建本机应用程序(例如使用 Electron),或者正在使用 Node.js 则可能更喜欢使用 SQLite 到 JavaScript 的本机绑定 (Native Binding of SQLite to JavaScript)。

本机绑定不仅速度更快,而且还能够直接处理数据库文件,而不必将整个数据库加载到内存中,从而避免内存不足错误并进一步提高性能。

目前 sql.js 在 Github 通过 MIT 协议开源,有超过 12.2k 的star、1k 的fork、项目依赖量6.8k、代码贡献者 50+ ,妥妥的前端优质开源项目。

2.如何使用 sql.js

浏览器中使用

默认情况下,sql.js 使用 wasm,因此除了 javascript 库之外还需要加载 .wasm 文件。 从 npm 安装 sql.js 后,开发者可以在 ./node_modules/sql.js/dist/sql-wasm.wasm 中找到此文件,并指示捆绑程序将其添加到静态资产或从 CDN 加载。

然后使用传递给 initSqlJs 的配置对象的 locateFile 属性来指示文件所在的位置。 如果使用 webpack 等构建器,则可以自动执行此操作。

const initSqlJs = require('sql.js');

const SQL = await initSqlJs({
  // 需要异步加载 wasm 二进制文件
  //  在 node 中运行时可以完全省略 locateFile
  locateFile: file => `https://sql.js.org/dist/${file}`
});

// 创建数据库
const db = new SQL.Database();
// 执行包含多个语句的单个 SQL 字符串
let sqlstr = "CREATE TABLE hello (a int, b char); \
INSERT INTO hello VALUES (0, 'hello'); \
INSERT INTO hello VALUES (1, 'world');";
db.run(sqlstr);
// 准备一条 sql 语句
const stmt = db.prepare("SELECT * FROM hello WHERE a=:aval AND b=:bval");

// 将值绑定到参数并获取查询结果
const result = stmt.getAsObject({':aval' : 1, ':bval' : 'world'});
console.log(result);
// 输出值 {a:1, b:'world'}

stmt.bind([0, 'hello']);
stmt.free();
const res = db.exec("SELECT * FROM hello");
/* 输出
[
  {columns:['a','b'], values:[[0,'hello'],[1,'world']]}
]
*/
db.create_aggregate(
  "json_agg",
  {
    init: () => [],
    step: (state, val) => [...state, val],
    finalize: (state) => JSON.stringify(state),
  }
);
db.exec("SELECT json_agg(column1) FROM (VALUES ('hello'), ('world'))");
// -> 输出值 '["hello","world"]'

// 将数据库导出到包含 SQLite 数据库文件的 Uint8Array
const binaryArray = db.export();

Node.js 环境中

sql.js 托管在 npm 上,只需运行 npm install sql.js 即可。或者,开发者可以简单地从下面的下载链接下载 sql-wasm.js 和 sql-wasm.wasm。

在 Node.js 环境中,可以通过下面代码从磁盘读取数据库:

const fs = require('fs');
const initSqlJs = require('sql-wasm.js');
const filebuffer = fs.readFileSync('test.sqlite');

initSqlJs().then(function(SQL){
  // 读取 DB
  const db = new SQL.Database(filebuffer);
});

同时,可以通过下面方法将内容写入磁盘:

const fs = require("fs");
// [...] (create the database)
const data = db.export();
const buffer = Buffer.from(data);
fs.writeFileSync("filename.sqlite", buffer);

同时,如果开发者不想在主应用程序线程中运行 CPU 密集型 SQL 查询,则可以使用更受限制的 WebWorker API。

  const worker = new Worker("/dist/worker.sql-wasm.js");
  worker.onmessage = () => {
    console.log("Database opened");
    worker.onmessage = event => {
      console.log(event.data);
      // 查询结果
    };

    worker.postMessage({
      id: 2,
      action: "exec",
      sql: "SELECT age,name FROM test WHERE id=$id",
      params: {"$id": 1}
    });
  };

  worker.onerror = e => console.log("Worker error:", e);
  worker.postMessage({
    id:1,
    action:"open",
    buffer:buf,
     /* 可选,代表 SQLite 数据库文件的 ArrayBuffer*/
  });

sql.js 还支持与 XMLHttpRequest 一起使用,比如下面的示例:

const xhr = new XMLHttpRequest();
// For example: https://github.com/lerocha/chinook-database/raw/master/ChinookDatabase/DataSources/Chinook_Sqlite.sqlite
xhr.open('GET', '/path/to/database.sqlite', true);
xhr.responseType = 'arraybuffer';

xhr.onload = e => {
  const uInt8Array = new Uint8Array(xhr.response);
  const db = new SQL.Database(uInt8Array);
  const contents = db.exec("SELECT * FROM my_table");
  // contents is now [{columns:['col1','col2',...], values:[[first row], [second row], ...]}]
};
xhr.send();

更多关于 Sql.js 的知识和用法可以参考文末资料,本文不再过多展开。

参考资料

https://madewithwebassembly.com/showcase/sqlite/

https://github.com/sql-js/sql.js

https://www.youtube.com/watch?app=desktop&v=0DZ472GiVNw

https://blog.logrocket.com/detailed-look-basic-sqljs-features/

相关推荐

python入门到脱坑函数—定义函数_如何定义函数python

Python函数定义:从入门到精通一、函数的基本概念函数是组织好的、可重复使用的代码块,用于执行特定任务。在Python中,函数可以提高代码的模块性和重复利用率。二、定义函数的基本语法def函数名(...

javascript函数的call、apply和bind的原理及作用详解

javascript函数的call、apply和bind本质是用来实现继承的,专业点说法就是改变函数体内部this的指向,当一个对象没有某个功能时,就可以用这3个来从有相关功能的对象里借用过来...

JS中 call()、apply()、bind() 的用法

其实是一个很简单的东西,认真看十分钟就从一脸懵B到完全理解!先看明白下面:例1obj.objAge;//17obj.myFun()//小张年龄undefined例2shows(...

Pandas每日函数学习之apply函数_apply函数python

apply函数是Pandas中的一个非常强大的工具,它允许你对DataFrame或Series中的数据应用一个函数,可以是自定义的函数,也可以是内置的函数。apply可以作用于DataF...

Win10搜索不习惯 换个设定就好了_window10搜索用不了怎么办

Windows10的搜索功能是真的方便,这点用惯了Windows10的小伙伴应该都知道,不过它有个小问题,就是Windows10虽然会自动联网搜索,但默认使用微软自家的Bing搜索引擎和Edge...

面试秘籍:call、bind、apply的区别,面试官为什么总爱问这三位?

引言你有没有发现,每次JavaScript面试,面试官总爱问你call、bind和apply的区别?好像这三个方法成了通关密码,掌握了它们,就能顺利过关。其实不难理解,面试官问这些问题,不...

记住这8招,帮你掌握“追拍“摄影技法—摄影早自习第422日

杨海英同学提问:请问叶梓老师,我练习追拍时,总也不能把运动的人物拍清晰,速度一般掌握在1/40-1/60,请问您如何把追拍拍的清晰?这跟不同的运动形式有关系吗?请您给讲讲要点,谢谢您!摄影:Damia...

[Sony] 有点残酷的测试A7RII PK FS7

都是好机!手中利器!主要是最近天天研究fs5,想知道fs5与a7rii后期匹配问题,苦等朋友的fs5月底到货,于是先拿手里现有的fs7小测一下,十九八九也能看到fs5的影子,另外也了解一下fs5k标配...

AndroidStudio_Android使用OkHttp发起Http请求

这个okHttp的使用,其实网络上有很多的案例的,但是,如果以前没用过,copy别人的直接用的话,可以发现要么导包导不进来,要么,人家给的代码也不完整,这里自己整理一下.1.引入OkHttp的jar...

ESL-通过事件控制FreeSWITCH_es事务控制

通过事件提供的最底层控制机制,允许我们有效地利用工具箱,适时选择使用其中的单个工具。FreeSWITCH是一个核心交换与混合矩阵,它周围有几十个模块提供各种功能特性。我们完全控制了所有的即时信息,这些...

【调试】perf和火焰图_perf生成火焰图

简介perf是linux上的性能分析工具,perf可以对event进行统计得到event的发生次数,或者对event进行采样,得到每次event发生时的相关数据(cpu、进程id、运行栈等),利用这些...

文本检索控件也玩安卓?dtSearch Engine发布Android测试版

dtSearchEngineforLinux(原生64-bit/32-bitC++和JavaAPIs)和dtSearchEngineforWin&.NET(原生64-bi...

网站后台莫名增加N个管理员,记一次SQL注入攻击

网站没流量,但却经常被SQL注入光顾。最近,网站真的很奇怪,网站后台不光莫名多了很多“管理员”,所有的Wordpres插件还会被自动暂停,导致一些插件支持的页面,如WooCommerce无法正常访问、...

多元回归树分析Multivariate Regression Trees,MRT

多元回归树(MultivariateRegressionTrees,MRT)是单元回归树的拓展,是一种对一系列连续型变量递归划分成多个类群的聚类方法,是在决策树(decision-trees)基础...

JMETER性能测试_JMETER性能测试指标

jmeter为性能测试提供了一下特色:jmeter可以对测试静态资源(例如js、html等)以及动态资源(例如php、jsp、ajax等等)进行性能测试jmeter可以挖掘出系统最大能处...