uni-app是什么东东,这里就不是多讲了,大家可以看下官网:https://uniapp.dcloud.net.cn/。总之以后,但有实体程序,大多用它来书写。SQLite是什么东西?我认为就是一个本地数据库,可以用SQL语句来完成数据库的操作。写本文是为了备忘,也是为积累知识。
一、创建uni-app项目
打开HBuilder,新建一个支持SQLite的项目。具体操作如下:
1、新建一个空项目
选默认模板,就可以了。也就是空的,不要选其他。
2、自动生成项目之后,在左侧找开项目,找到个manifest.json,如图:
这个文件就是项目的配置文件,一定要看好
3、如果你生成的项目,没有AppID,则点“生新获取"。如果有AppID,则直接略过:
操作之后结果,如下图所示,但是注意你生成的AppID可能不一样:
4、在App模块配置之中,选中SQLite,操作如图所示:
这个文件通常是自动保存的,也可以手工保存一下。理论上讲,我们现在已经可以操作SQLite了,但是我们还要先了解一下操作的API;看一下,系统为我们提供那些接口,来操作SQLite
二、操作SQLite的API
SQLite,是一款轻型的数据库,是遵守ACID的关系型数据库管理系统,它包含在一个相对小的C库中。它是D.RichardHipp建立的公有领域项目。它的设计目标是嵌入式的,而且已经在很多嵌入式产品中使用了它,它占用资源非常的低,在嵌入式设备中,可能只需要几百K的内存就够了。它能够支持Windows/Linux/Unix等等主流的操作系统,同时能够跟很多程序语言相结合,比如 Tcl、C#、PHP、Java等,还有ODBC接口,同样比起Mysql、PostgreSQL这两款开源的世界著名数据库管理系统来讲,它的处理速度比他们都快。SQLite第一个Alpha版本诞生于2000年5月。 至2023年已经接近有23个年头,SQLite也迎来了一个版本 SQLite 3已经发布。
我们的API,还要记得一个网址:https://www.html5plus.org/doc/zh_cn/sqlite.html,打后之后如图所示:
下面我们先来了解一下这个文档
1、打开数据库
void plus.sqlite.openDatabase(options);
说明: \color{red}说明: 说明:
如果数据库存在则打开,不存在则创建。参数: \color{red}参数: 参数:
options参数为json类型,包含以下属性:
- name: ( String ) 必选 数据库名称 如chat
- path: ( String ) 必选 数据库路径 如_doc/chat.db
- success: ( SQLiteSuccessCallback ) 可选 打开数据库成功回调函数,回调函数无返回参数。
- fail: ( SQLiteFailCallback ) 可选 打开数据库失败回调函数
例子:
// 打开数据库 function openDB(){ plus.sqlite.openDatabase({ name: 'first', path: '_doc/test.db', success: function(e){ console.log('openDatabase success!'); }, fail: function(e){ console.log('openDatabase failed: '+JSON.stringify(e)); } }); }
2、判断数据库是否打开
Boolean plus.sqlite.isOpenDatabase(options);
说明: \color{red}说明: 说明:
数据库已经打开则返回true,数据库没有打开则返回false。参数: \color{red}参数: 参数:
options参数为json类型,包含以下属性:
- name: ( String ) 必选 数据库名称
- path: ( String ) 必选 数据库路径
返回值: \color{red}返回值: 返回值:
Boolean : true表示数据库已打开,false表示数据库没有打开。例子:
if (plus.sqlite.isOpenDatabase({name: 'first',path: '_doc/test.db'})){ console.log('已经打开数据库。'); }else{ console.log('没有打开数据库!'); }
3、关闭数据库
void plus.sqlite.closeDatabase(options);
说明: \color{red}说明: 说明:
完成数据库操作后,必须关闭数据库,否则可能会导致系统资源无法释放。参数: \color{red}参数: 参数:
options参数为json类型,包含以下属性:
- name: ( String ) 必选 数据库名称
- success: ( SQLiteSuccessCallback ) 可选 关闭数据库成功回调函数,回调函数无返回参数。
- fail: ( SQLiteFailCallback ) 可选 关闭数据库失败回调函数
示例:
// 关闭数据库 function closeDB(){ plus.sqlite.closeDatabase({ name: 'first', success: function(e){ console.log('closeDatabase success!'); }, fail: function(e){ console.log('closeDatabase failed: '+JSON.stringify(e)); } }); }
4、执行事务
void plus.sqlite.transaction(options);
参数: \color{red}参数: 参数:
options参数为json类型,包含以下属性:
- name: ( String ) 必选 数据库名称
- operation: ( String ) 必选 需要执行的事务操作
- begin(开始事务)
- commit(提交)
- rollback(回滚)
- success: ( SQLiteSuccessCallback ) 可选 执行事务成功回调函数,回调函数无返回参数。
- fail: ( SQLiteFailCallback ) 可选 执行事务失败回调函数
返回值: \color{red}返回值: 返回值:
void : 无示例:
// 执行事务 function transactionDB(){ plus.sqlite.transaction({ name: 'first', operation: 'begin', success: function(e){ console.log('transaction success!'); }, fail: function(e){ console.log('transaction failed: '+JSON.stringify(e)); } }); }
5、执行增删改等操作的SQL语句
void plus.sqlite.executeSql(options);
参数: \color{red}参数: 参数:
options参数为json类型,包含以下属性:
- name: ( String ) 必选 数据库名称
- sql: ( Array[String] | String ) 必选 需要执行的SQL语句
- 参数为字符串时,表示执行单条SQL语句;
- 参数为字符串数组时,表示执行多条SQL语句,按数组顺序执行,某条SQL语句执行错误则终止。
. + 注意:不支持SQL语句中使用“;”分割多条命令,要运行多条命令请使用字符串数组参数。- success: ( SQLiteSuccessCallback ) 可选 执行SQL语句成功回调函数
- 回调函数无返回参数。
- fail: ( SQLiteFailCallback ) 可选 执行SQL语句失败回调函数
示例:
// 执行SQL语句 function executeSQL(){ plus.sqlite.executeSql({ name: 'first', sql: 'create table if not exists database("where" CHAR(110),"location" CHAR(100),"age" INT(11))', success: function(e){ console.log('executeSql success!'); plus.sqlite.executeSql({ name: 'first', sql: "insert into database values('北京','安乐林','11')", success: function(e){ console.log('executeSql success!'); }, fail: function(e){ console.log('executeSql failed: '+JSON.stringify(e)); } }); }, fail: function(e){ console.log('executeSql failed: '+JSON.stringify(e)); } }); }
6、执行查询的SQL语句
void plus.sqlite.selectSql(options);
参数: \color{red}参数: 参数:
options参数为json类型,包含以下属性:
- name: ( String ) 必选 数据库名称
- sql: ( String ) 必选 需要查询的SQL语句
- success: ( SQLiteSuccessCallback ) 可选 执行SQL语句成功回调函数
- 回调函数返回参数为JSON对象数组,其中JSON对象为查询的结果。 如果未查询到数据则返回参数为空数组。
- fail: ( SQLiteFailCallback ) 可选 执行SQL语句失败回调函数
示例:
// 查询SQL语句 function selectSQL(){ plus.sqlite.selectSql({ name: 'first', sql: 'select * from database', success: function(data){ console.log('selectSql success: '); for(var i in data){ console.log(data[i]); } }, fail: function(e){ console.log('selectSql failed: '+JSON.stringify(e)); } }); }
三、直接引用
我们现在来制作原始的接口,俱体的方法是找到我们的主文件:pages\index\index.vue。在这个文件开头,写入以下代码:
源码如下:<view class="title">原始接口0</view> <view style="display: flex;flex-direction: row;flex-wrap: wrap;justify-content:flex-start;justify-items: auto;"> <button style="width: 30%;margin-bottom: 10rpx;" @click="openDB">打开DB</button> <button style="width: 30%;margin-bottom: 10rpx;" @click="isopen">是否打开</button> <button style="width: 30%;margin-bottom: 10rpx;" @click="closeDB">关闭DB</button> <button style="width: 30%;margin-bottom: 10rpx;" @click="executeSQL">执行SQL</button> <button style="width: 30%;margin-bottom: 10rpx;" @click="selectSQL">查询SQL</button> <button style="width: 30%;margin-bottom: 10rpx;" @click="transBegin">事务开始</button> <button style="width: 30%;margin-bottom: 10rpx;" @click="editDB">岁数+1</button> <button style="width: 30%;margin-bottom: 10rpx;" @click="transCommit">事务提交</button> <button style="width: 30%;margin-bottom: 10rpx;" @click="transRollback">事务回滚</button> </view>
在 methods: 处,加上我们改写的代码。
1、打开数据库接口:
//打开数据库
openDB(){
plus.sqlite.openDatabase({
name: 'first',
path: '_doc/test.db',
success: function(e){
console.log('openDatabase success!');
},
fail: function(e){
console.log('openDatabase failed: '+JSON.stringify(e));
}
});
},
拷上面代码,去function,最后再上加**,**就可以了。以后的代码也是这样改。
2、数据库是否打开:
//db是否打开
isopen(){
if (plus.sqlite.isOpenDatabase({name: 'first',path: '_doc/test.db'})){
console.log('已经打开数据库。');
return true;
}else{
console.log('没有打开数据库!');
return false;
}
},
这应该算一个同步函数
3、关闭数据库:
closeDB(){
plus.sqlite.closeDatabase({
name: 'first',
success: function(e){
console.log('closeDatabase success!');
},
fail: function(e){
console.log('closeDatabase failed: '+JSON.stringify(e));
}
});
},
每次操作数据库,都要关闭!
4、执行SQL语句:
executeSQL(){
plus.sqlite.executeSql({
name: 'first',
sql: 'create table if not exists database("where" CHAR(110),"location" CHAR(100),"age" INT(11))',
success: function(e){
console.log('executeSql success!');
plus.sqlite.executeSql({
name: 'first',
sql: "insert into database values('北京','安乐林','11')",
success: function(e){
console.log('executeSql success!');
},
fail: function(e){
console.log('executeSql failed: '+JSON.stringify(e));
}
});
},
fail: function(e){
console.log('executeSql failed: '+JSON.stringify(e));
}
});
},
这个函数有点长,不过不用改逻辑,我们要试一下,能不能运行,接口是不是OK!
5、查询SQL语句
selectSQL(){
plus.sqlite.selectSql({
name: 'first',
sql: 'select * from database',
success: function(data){
console.log('selectSql success: ');
for(var i in data){
console.log(data[i]);
}
},
fail: function(e){
console.log('selectSql failed: '+JSON.stringify(e));
}
});
},
这种函数,没有通用性
6、执行事务(开始)
transBegin(){
plus.sqlite.transaction({
name: 'first',
operation: 'begin',
success: function(e){
console.log('transaction begin success!');
},
fail: function(e){
console.log('transaction begin failed: '+JSON.stringify(e));
}
});
},
事务接口,必须扩一下,扩成三个开始、提交、回滚
7、执行事务(提交)
transCommit(){
plus.sqlite.transaction({
name: 'first',
operation: 'commit',
success: function(e){
console.log('transaction commit success!');
},
fail: function(e){
console.log('transaction commit failed: '+JSON.stringify(e));
}
});
},
8、执行事务(回滚)
transRollback(){
plus.sqlite.transaction({
name: 'first',
operation: 'rollback',
success: function(e){
console.log('transaction rollback success!');
},
fail: function(e){
console.log('transaction rollback failed: '+JSON.stringify(e));
}
});
},
9、修改数据事务用
editDB(){
plus.sqlite.executeSql({
name: 'first',
sql: "update database set age=age+1 ",
success: function(e){
console.log('executeSql update success!');
},
fail: function(e){
console.log('executeSql update failed: '+JSON.stringify(e));
}
});
},
这是事务中要用的,只要开启事务,修改数据,在提交后有效。如果回滚则无效!
10、小结:
这个接口是可以用的,特别是事务也是可以用!这对于关键业务相当有用。但是缺点也常非明显,不方便使用,我们在目前的基础之上,可以进化到一个单独的js文件中。
四、第1代接口
1、我们改template,增加如下代码:
<hr>
<view class="title">第1代接口</view>
<view style="display: flex;flex-direction: row;flex-wrap: wrap;justify-content:flex-start;justify-items: auto;">
<button style="width: 30%;margin-bottom: 10rpx;" @click="clickOpenDB">打开DB</button>
<button style="width: 30%;margin-bottom: 10rpx;" @click="clickIsOpen">是否打开</button>
<button style="width: 30%;margin-bottom: 10rpx;" @click="clickCloseDB">关闭DB</button>
<button style="width: 30%;margin-bottom: 10rpx;" @click="clickExecuteSQL">执行SQL</button>
<button style="width: 30%;margin-bottom: 10rpx;" @click="clickSelectSQL">查询SQL</button>
<button style="width: 30%;margin-bottom: 10rpx;" @click="clickTransBegin">事务开始</button>
<button style="width: 30%;margin-bottom: 10rpx;" @click="clickEditDB">岁数+1</button>
<button style="width: 30%;margin-bottom: 10rpx;" @click="clickTransCommit">事务提交</button>
<button style="width: 30%;margin-bottom: 10rpx;" @click="clickTransRollback">事务回滚</button>
</view>
2、我们新建目录common,并在其目录下建立新js文件:SQLite31.js,效果如图所示:
//第一代SQLite接口,作者:天一先生,时间:2023-8-12
//打开数据库
function openDB(config){
plus.sqlite.openDatabase({
...config,
success: function(e){
console.log('openDatabase success!');
},
fail: function(e){
console.log('openDatabase failed: '+JSON.stringify(e));
}
});
}
//db是否打开
function isOpen(config){
if (plus.sqlite.isOpenDatabase(config)){
console.log('已经打开数据库。');
return true;
}else{
console.log('没有打开数据库!');
return false;
}
}
// 关闭数据库
function closeDB(config){
plus.sqlite.closeDatabase({
...config,
success: function(e){
console.log('closeDatabase success!');
},
fail: function(e){
console.log('closeDatabase failed: '+JSON.stringify(e));
}
});
}
// 执行SQL语句
function executeSQL(config,sql){
plus.sqlite.executeSql({
...config,
sql: sql,
success: function(e){
console.log('executeSql success!');
},
fail: function(e){
console.log('executeSql failed: '+JSON.stringify(e));
}
});
}
// 查询SQL语句
function selectSQL(config,sql){
plus.sqlite.selectSql({
...config,
sql: sql,
success: function(data){
console.log('selectSql success: ');
for(var i in data){
console.log(data[i]);
}
},
fail: function(e){
console.log('selectSql failed: '+JSON.stringify(e));
}
});
}
// 执行事务(开始)begin,commit,rollback
function trans(config,oper){
plus.sqlite.transaction({
...config,
operation:oper,
success: function(e){
console.log('transaction '+oper+' success!');
},
fail: function(e){
console.log('transaction '+oper+' failed: '+JSON.stringify(e));
}
});
}
module.exports = {trans,selectSQL,executeSQL,closeDB,isOpen,openDB};
3、在主程序中我们引用这个js,在pages/index/index.vue的script
<script>
import sql1 from '@/common/SQLite31.js'
export default {
data() {
return {
title: 'Hello',
config:{name: 'first',path: '_doc/test.db'}
}
},
onLoad() {
//this.openDB();
},
4、在methods之中增加事件如下:
//==========================第1代接口=======================
clickOpenDB(){
sql1.openDB(this.config)
},
clickIsOpen(){
sql1.isOpen(this.config)
},
clickCloseDB(){
sql1.closeDB(this.config);
},
clickExecuteSQL(){
let sqltxt=['create table if not exists database("where" CHAR(110),"location" CHAR(100),"age" INT(11))',
"insert into database values('北京','安乐林','11')"];
sql1.executeSQL(this.config,sqltxt);
},
clickSelectSQL(){
let sqltxt='select * from database';
sql1.selectSQL(this.config,sqltxt);
},
clickTransBegin(){
sql1.trans(this.config,'begin');
},
clickEditDB(){
let sqltxt="update database set age=age+1 ";
sql1.executeSQL(this.config,sqltxt);
},
clickTransCommit(){
sql1.trans(this.config,'commit');
},
clickTransRollback(){
sql1.trans(this.config,'rollback');
},
5、小结:我们已经做了接口,也用独立文件来表达。但是使用还是不方便,比如不能方便的使用连续两条SQL,必须要在回调中才安全。如果遇上复杂一点的SQL,我们就难以搞定。所以必须继续进行同步化!
五、第2代接口
1、同步化我们采用 async/promise/await来处理所有的已知函数,以isOpen为例说明,未同化前:
//db是否打开
function isOpen(config){
if (plus.sqlite.isOpenDatabase(config)){
console.log('已经打开数据库。');
return true;
}else{
console.log('没有打开数据库!');
return false;
}
}
同化之后
//db是否打开
async function isOpen(config){
return new Promise((callback)=>{
if (plus.sqlite.isOpenDatabase(config)){
callback({code:1,msg:'已经打开数据库。'});
}else{
callback({code:0,msg:'没有打开数据库!'});
}
});
}
如何使用同化后的函数呢?
在模板之中:
<button style="width: 30%;margin-bottom: 10rpx;" @click="onclickIsOpen">是否打开</button>
在脚本之中:
<script>
import sql2 from '@/common/SQLite32.js'
......
methods: {
...
async onclickIsOpen(){
let res=await sql2.isOpen(this.config);
if (res.code==1) console.log('已经打开');
else console.log(res.msg);
},
事实上我们规定,所有同步函数都返回:{code:code,msg:msg,data:[]}
code,msg是必须的,data是可选的;code=1是操作成功,code=0是操作失败,msg:是成功信息或出错信息,data是数据
2、我们在主页面的template,增加如下代码:
<hr>
<view class="title">第2代接口</view>
<view style="display: flex;flex-direction: row;flex-wrap: wrap;justify-content:flex-start;justify-items: auto;">
<button style="width: 30%;margin-bottom: 10rpx;" @click="onclickOpenDB">打开DB</button>
<button style="width: 30%;margin-bottom: 10rpx;" @click="onclickIsOpen">是否打开</button>
<button style="width: 30%;margin-bottom: 10rpx;" @click="onclickCloseDB">关闭DB</button>
<button style="width: 30%;margin-bottom: 10rpx;" @click="onclickExecuteSQL">执行SQL</button>
<button style="width: 30%;margin-bottom: 10rpx;" @click="onclickSelectSQL">查询SQL</button>
<button style="width: 30%;margin-bottom: 10rpx;" @click="onclickTransBegin">事务开始</button>
<button style="width: 30%;margin-bottom: 10rpx;" @click="onclickEditDB">岁数+1</button>
<button style="width: 30%;margin-bottom: 10rpx;" @click="onclickTransCommit">事务提交</button>
<button style="width: 30%;margin-bottom: 10rpx;" @click="onclickTransRollback">事务回滚</button>
</view>
3、新建common/SQLite32.js如下:
/*
名称: SQLite32.js
作者: 天一
功能: SQLite3的同步接口
开创: 2023-08-12
最新: 2023-08-13
*/
// 打开数据库
async function openDB(config){
return new Promise((callback)=>{
plus.sqlite.openDatabase({
...config,
success: function(e){
callback({code:1,msg:'打开数据库 成功!'})
},
fail: function(e){
callback({code:0,msg:'打开数据库 失败: '+JSON.stringify(e)})
}
});
})
}
//db是否打开
async function isOpen(config){
return new Promise((callback)=>{
if (plus.sqlite.isOpenDatabase(config)){
callback({code:1,msg:'已经打开数据库。'});
}else{
callback({code:0,msg:'没有打开数据库!'});
}
});
}
// 关闭数据库
async function closeDB(config){
return new Promise((callback)=>{
plus.sqlite.closeDatabase({
...config,
success: function(e){
console.log('closeDatabase success!');
callback({code:1,msg:'关闭数据库成功。'});
},
fail: function(e){
callback({code:0,msg:'关闭数据库失败:'+JSON.stringify(e)});
}
});
});
}
// 执行SQL语句
async function executeSQL(config,sql){
return new Promise((callback)=>{
plus.sqlite.executeSql({
...config,
sql: sql,
success: function(e){
callback({code:1,msg:e});
},
fail: function(e){
callback({code:0,msg:'执行SQL失败:'+JSON.stringify(e)});
}
});
});
}
// 查询SQL语句
async function selectSQL(config,sql){
return new Promise((callback)=>{
plus.sqlite.selectSql({
...config,
sql: sql,
success: function(data){
callback({code:1,data:data,msg:'查询SQL成功'})
},
fail: function(e){
callback({code:0,data:[],msg:'查询SQL失败: '+JSON.stringify(e)})
}
});
});
}
// 执行事务(oper)begin,commit,rollback
async function transaction(config,oper){
return new Promise((callback)=>{
plus.sqlite.transaction({
...config,
operation:oper,
success: function(e){
callback({code:1,msg:'事务 '+oper+' 成功'});
},
fail: function(e){
callback({code:0,msg:'事务 '+oper+' 失败:'+JSON.stringify(e)});
}
});
});
}
module.exports = {closeDB,openDB,isOpen,executeSQL,selectSQL,transaction};
4、在主程序中我们引用这个js,在pages/index/index.vue的script
<script>
import sql2 from '@/common/SQLite32.js'
export default {
data() {
return {
title: 'Hello',
config:{name: 'first',path: '_doc/test.db'}
}
},
onLoad() {
//this.openDB();
},
5、在methods之中增加事件如下:
//==========================第2代接口==================
async onclickOpenDB(){
let res=await sql2.openDB(this.config);
if (res.code==1) console.log('打开成功');
else console.log(res.msg);
},
//
async onclickIsOpen(){
let res=await sql2.isOpen(this.config);
if (res.code==1) console.log('已经打开');
else console.log(res.msg);
},
async onclickCloseDB(){
let res=await sql2.closeDB(this.config);
console.log(res);
},
async onclickExecuteSQL(){
let sqltxt=['create table if not exists database("where" CHAR(110),"location" CHAR(100),"age" INT(11))',
"insert into database values('北京','安乐林','11')"];
let res=await sql2.executeSQL(this.config,sqltxt);
console.log(res);
},
async onclickSelectSQL(){
let sqltxt='select * from database';
let res=await sql2.selectSQL(this.config,sqltxt);
console.log(res);
},
async onclickTransBegin(){
let res=await sql2.transaction(this.config,'begin');
console.log(res);
},
async onclickEditDB(){
let sqltxt="update database set age=age+1 ";
let res=await sql2.executeSQL(this.config,sqltxt);
console.log(res);
},
async onclickTransCommit(){
let res=await sql2.transaction(this.config,'commit');
console.log(res);
},
async onclickTransRollback(){
let res=await sql2.transaction(this.config,'rollback');
console.log(res);
},
6、小结:本文只是初谈,所有代码,已上传 https://gitcode.net/sinat_26699091/SQLiteDemo