目录
1、引入sqlite模块
1.1、android权限申请
1.2、权限配置
1.3、打包,制作自定义基座运行
2、sqlite文件结构
3、初始化文件index.js
4、打开数据库
5、查询数据
6、可视化测试
SQLite是一个进程内的库,实现了自给自足的、无服务器的、零配置的、事务性的 SQL 数据库引擎。它是一个零配置的数据库,这意味着与其他数据库不一样,您不需要在系统中配置。
就像其他数据库,SQLite 引擎不是一个独立的进程,可以按应用程序需求进行静态或动态连接。SQLite 直接访问其存储文件。
在App.vue 的onLaunch函数中定义,获取存储权限
// 判断有没有存储权限
var _this = this
plus.android.requestPermissions(['android.permission.WRITE_EXTERNAL_STORAGE'], function(e) {
console.log(e.deniedPresent)
if (e.deniedAlways.length > 0) { //权限被永久拒绝
// 弹出提示框解释为何需要读写手机储存权限,引导用户打开设置页面开启
uni.showModal({
title: '存储权限',
content: '您拒绝了存储权限,请去设置-应用开启存储权限。',
success: function (res) {
if (res.confirm) {
// console.log('用户点击确定');
} else if (res.cancel) {
// console.log('用户点击取消');
}
}
});
}
if (e.deniedPresent.length > 0) { //权限被临时拒绝
// 弹出提示框解释为何需要读写手机储存权限,可再次调用plus.android.requestPermissions申请权限
plus.android.requestPermissions(['android.permission.WRITE_EXTERNAL_STORAGE'])
// console.log('666666666 ' + e.deniedPresent.toString());
}
if (e.granted.length > 0) { //权限被允许
//调用依赖获取读写手机储存权限的代码
// _this.upload() // 获取权限成功之后调用的函数
// console.log('2222222222 ' + e.granted.toString());
}
}, function(e) {
// console.log('R12133313221' + JSON.stringify(e));
});
在manifest.json中提供可视化选择
另外附上权限列表:
后续的操作成功后,会在手机磁盘的根路径下生成transfer【数据库实例名】文件夹
里面包含transfer.db、transfer.db-shm、transfer.db-wal
其中transfer.db 可以通过navicat等工具打开
在项目根路径下定义db\sqlite文件夹
除了index.js属于初始化sqlite库文件,其余文件均表示对数据库相关表的操作
以boxDetail.js文件为例
在SysBoxDetail 函数内 init 方法,需要检查数据库表是否建立。
以及在已安装的应用程序后,对应的新增字段、索引、表数据修改等升级操作
提供对于表数据查询操作的相关函数
import {sqlite} from '@/db/sqlite/index.js'
import {strUtil, dateUtils} from '@/common/util.js'
const tabName = "sys_box_detail";
const fields = "id INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL,batchId INTEGER not null, "
+" boxId INTEGER, boxNo INTEGER not null, archNo text not null, createTime text,"
+" fileNum text not null, storeroom text"
// 类似于构造函数,必须定义
function BoxDetail(){
}
BoxDetail.prototype = {
constructor: BoxDetail,
}
export const SysBoxDetail = {
init: function(){
if(!sqlite.isOpen()){
sqlite.openDb();
}
return sqlite.isTable(tabName).then((res) => {
console.log(tabName+"是否存在:" + res)
if(!res) {
sqlite.createTab(tabName, fields)
} else {
// 用于后续升级版本 新增 fileNum字段
sqlite.existsField(tabName, 'fileNum').then(res => {
if(res[0].num == 0){
let sql = "ALTER TABLE "+tabName+" ADD COLUMN fileNum text DEFAULT 1"
sqlite.updateBySQL(sql).then(res => {
console.log(res)
console.log("插入字段成功")
})
}
})
// 新增 createTime字段
sqlite.existsField(tabName, 'createTime').then(res => {
if(res[0].num == 0){
let sql = "ALTER TABLE "+tabName+" ADD COLUMN createTime text"
sqlite.updateBySQL(sql).then(res => {
console.log(res)
console.log("插入字段成功")
})
}
})
}
// 新增索引
sqlite.existsIndex(tabName, tabName + '_idx_archNo').then( (res) => {
console.log('索引判断:',res)
if(res[0].num == 0){
sqlite.createIndex(tabName, tabName + '_idx_archNo', 'archNo')
sqlite.createIndex(tabName, tabName + '_idx_boxId', 'boxId')
sqlite.createIndex(tabName, tabName + '_idx_batchId', 'batchId')
sqlite.createIndex(tabName, tabName + '_idx_boxNo', 'boxNo')
}
})
// 移除不存在的批次数据 ,后期再有新版本可以删除该行
this.deleteByNotExistsBatchId();
})
},
insert: function(data){
return sqlite.addTabItem(tabName, data);
},
count: function(queryParam){
let sql = "select count(*) as num from " + tabName + this.where(queryParam);
return sqlite.selectBySQL(sql);
},
selectAll: function(queryParam){
let sql = "select * from " + tabName + this.where(queryParam);
let order = " order by archNo asc ";
return sqlite.selectBySQL(sql + order);
},
selectById: function(id){
let sql = `select * from ${tabName} where id = ${id}`;
return sqlite.selectBySQL(sql);
},
updateFileNumById: function(id, fileNum) {
let sql = `update ${tabName} set fileNum = ${fileNum} where id = ${id}`;
return sqlite.updateBySQL(sql);
},
deleteById: function(id){
return sqlite.deleteInformationType(tabName, {'id': id});
},
deleteByBoxId: function(boxId) {
return sqlite.deleteInformationType(tabName, {'boxId': boxId});
},
deleteByBatchId: function(batchId) {
return sqlite.deleteInformationType(tabName, {'batchId': batchId});
},
/**
* 移除无效的批次数据
*/
deleteByNotExistsBatchId: function(){
let sql = `delete from ${tabName} where batchId not in (select id from sys_batch )`;
return sqlite.updateBySQL(sql);
},
select: function(queryParam){
let sql = "select * from " + tabName + this.where(queryParam);
let order = " order by boxNo, archNo asc ";
let limit = this.limit(queryParam)
return sqlite.selectBySQL(sql + order + limit);
},
/**
* 关联boxId 查询,显示是否封箱
* @param {Object} queryParam
*/
selectWithBox: function(queryParam){
let sql = "select a.*,b.status from " + tabName + " as a left outer join sys_box as b on a.boxId = b.id "
let where = this.where(queryParam, 'a');
let order = " order by a.boxNo, a.archNo asc ";
let limit = this.limit(queryParam)
return sqlite.selectBySQL(sql + where + order + limit);
},
countByBatchNo: function(batchNo){
let sql = "select count(*) as num from " + tabName + this.where({batchNo: batchNo});
return sqlite.selectBySQL(sql);
},
countByArchNoAndBatchId: function(archNo, batchId){
let sql = "select count(*) as num from " + tabName +
this.where({archNo: archNo, batchId: batchId});
return sqlite.selectBySQL(sql);
},
where: function(queryParam, alias){
let where = ''
if(strUtil.isEmpty(alias)){
alias = ''
} else {
alias +='.'
}
if(queryParam){
var batchId = queryParam.batchId;
if(strUtil.isNotEmpty(batchId)){
where += ` and ${alias}batchId = ${batchId} `;
}
var boxId = queryParam.boxId;
if(strUtil.isNotEmpty(boxId)){
where += ` and ${alias}boxId = ${boxId}`;
}
var archNo = queryParam.archNo;
if(strUtil.isNotEmpty(archNo)){
where += ` and ${alias}archNo = "${archNo}" `
}
var searchValue = queryParam.searchValue;
if(strUtil.isNotEmpty(searchValue)){
where += ` and ( ${alias}boxNo = "${searchValue}" or ${alias}storeroom = "${searchValue}" or ${alias}archNo like "%${searchValue}%" )`
}
}
if(where.length > 0){
where = " where 1=1 " + where;
}
return where;
},
limit: function(queryParam){
let num = queryParam.pageNum;
let size = queryParam.pageSize
let numindex = 0
if(num <= 1){
numindex = 0
} else {
numindex = ((num - 1) * size)
}
return ` limit ${numindex},${size}`
}
}
注意实际数据文件存放位置 ,有的手机会限制根路径存储,要求在应用自身层级下
path: `/storage/emulated/0/transfer/${dbName}.db`,
// 定义数据库实例名称
let dbName = "transfer"
export const openDb = () => {
//如果数据库存在则打开,不存在则创建。
return new Promise((resolve, reject) => {
plus.sqlite.openDatabase({
name: dbName, //数据库名称
// path: `_doc/${dbName}.db`, //数据库地址
path: `/storage/emulated/0/transfer/${dbName}.db`,
success(e) {
console.log(e)
resolve(e);
},
fail(e) {
console.log(e)
reject(e);
}
})
})
}
// 查询所有数据表名
export const getTable = () => {
return new Promise((resolve, reject) => {
plus.sqlite.selectSql({
name: dbName,
sql: "select * FROM sqlite_master where type='table'",
success(e) {
resolve(e);
},
fail(e) {
console.log(e)
reject(e);
}
})
})
}
// 查询表数据总条数
export const getCount = (tabName) => {
return new Promise((resolve, reject) => {
plus.sqlite.selectSql({
name: dbName,
sql: "select count(*) as num from " + tabName,
success(e) {
resolve(e);
},
fail(e) {
reject(e);
}
})
})
}
// 查询表是否存在
export const isTable = (tabName) => {
return new Promise((resolve, reject) => {
plus.sqlite.selectSql({
name: dbName,
sql: `select count(*) as isTable FROM sqlite_master where type='table' and name='${tabName}'`,
success(e) {
resolve(e[0].isTable ? true : false);
},
fail(e) {
console.log(e)
reject(e);
}
})
})
}
// 修改数据
export const updateBySQL = (sql) => {
console.log(sql)
return new Promise((resolve, reject) => {
plus.sqlite.executeSql({
name: dbName,
sql: sql,
success(e) {
console.log(e)
resolve(e);
},
fail(e) {
console.log(e)
reject(e);
}
})
})
}
// 修改数据
export const updateSQL = (tabName, setData, setName, setVal) => {
if (JSON.stringify(setData) !== '{}') {
let dataKeys = Object.keys(setData)
let setStr = ''
dataKeys.forEach((item, index) => {
console.log(setData[item])
setStr += (
`${item} = ${JSON.stringify(setData[item])}${dataKeys.length - 1 !== index ? "," : ""}`)
})
console.log(setStr)
return new Promise((resolve, reject) => {
plus.sqlite.executeSql({
name: dbName,
sql: `update ${tabName} set ${setStr} where ${setName} = "${setVal}"`,
success(e) {
console.log(e)
resolve(e);
},
fail(e) {
console.log(e)
reject(e);
}
})
})
} else {
return new Promise((resolve, reject) => {
reject("错误")
});
}
}
//删除数据库数据
export const deleteInformationType = (tabName,setData) => {
if (JSON.stringify(setData) !== '{}') {
let dataKeys = Object.keys(setData)
let setStr = ''
dataKeys.forEach((item, index) => {
console.log(setData[item])
setStr += (
`${item}=${JSON.stringify(setData[item])}${dataKeys.length - 1 !== index ? " and " : ""}`)
})
let sql = `delete from ${tabName} where ${setStr}`
console.log(sql)
return new Promise((resolve, reject) => {
plus.sqlite.executeSql({
name: dbName,
sql: sql,
success(e) {
resolve(e);
},
fail(e) {
reject(e);
}
})
})
} else {
return new Promise((resolve, reject) => {
reject("错误")
});
}
}
//关闭数据库
export const closeSQL = () => {
return new Promise((resolve, reject) => {
plus.sqlite.closeDatabase({
name: dbName,
success(e) {
resolve(e);
},
fail(e) {
reject(e);
}
})
})
}
//监听数据库是否开启
export const isOpen = () => {
let open = plus.sqlite.isOpenDatabase({
name: dbName,
path: `_doc/${dbName}.db`,
})
return open;
}
// 创建表
export const createTab = (tabName, data) => {
// tabName不能用数字作为表格名的开头
return new Promise((resolve, reject) => {
console.log("创建数据库表",tabName)
plus.sqlite.executeSql({
name: dbName,
// sql: 'create table if not exists dataList("list" INTEGER PRIMARY KEY AUTOINCREMENT,"id" TEXT,"name" TEXT,"gender" TEXT,"avatar" TEXT)',
sql: `create table if not exists ${tabName}(${data})`,
success(e) {
cosole.log("创建数据表成功")
resolve(e);
},
fail(e) {
console.log(e)
reject(e);
}
})
})
}
// 创建表
export const dropTab = (tabName) => {
if(null == tabName || tabName.length == 0){
return false;
}
// tabName不能用数字作为表格名的开头
return new Promise((resolve, reject) => {
plus.sqlite.executeSql({
name: dbName,
// sql: 'create table if not exists dataList("list" INTEGER PRIMARY KEY AUTOINCREMENT,"id" TEXT,"name" TEXT,"gender" TEXT,"avatar" TEXT)',
sql: `DROP TABLE ${tabName}`,
success(e) {
cosole.log(`删除数据表成功`)
resolve(e);
},
fail(e) {
console.log(e)
reject(e);
}
})
})
}
// 添加数据
export const addTabItem = (tabName,obj) => {
if (obj) {
let keys = Object.keys(obj)
let keyStr = keys.toString()
let valStr = ''
keys.forEach((item, index) => {
if (keys.length - 1 == index) {
valStr += ('"' + obj[item] + '"')
} else {
valStr += ('"' + obj[item] + '",')
}
})
console.log(valStr)
let sqlStr = `insert into ${tabName}(${keyStr}) values(${valStr})`
console.log(sqlStr)
return new Promise((resolve, reject) => {
plus.sqlite.executeSql({
name: dbName,
sql: sqlStr,
success(e) {
resolve(e);
},
fail(e) {
console.log(e)
reject(e);
}
})
})
} else {
return new Promise((resolve, reject) => {
reject("错误")
})
}
}
// 合并数据
export const mergeSql = (tabName,tabs) => {
if (!tabs || tabs.length == 0) {
return new Promise((resolve, reject) => {
reject("错误")
})
}
let itemValStr = ''
tabs.forEach((item, index) => {
let itemKey = Object.keys(item)
let itemVal = ''
itemKey.forEach((key, i) => {
if (itemKey.length - 1 == i) {
if (typeof item[key] == 'object') {
itemVal += (`'${JSON.stringify(item[key])}'`)
} else {
itemVal += (`'${item[key]}'`)
}
} else {
if (typeof item[key] == 'object') {
itemVal += (`'${JSON.stringify(item[key])}',`)
} else {
itemVal += (`'${item[key]}',`)
}
}
})
if (tabs.length - 1 == index) {
itemValStr += ('(' + itemVal + ')')
} else {
itemValStr += ('(' + itemVal + '),')
}
})
let keys = Object.keys(tabs[0])
let keyStr = keys.toString()
return new Promise((resolve, reject) => {
plus.sqlite.executeSql({
name: dbName,
sql: `insert or ignore into ${tabName} (${keyStr}) values ${itemValStr}`,
success(e) {
resolve(e);
},
fail(e) {
console.log(e)
reject(e);
}
})
})
}
// 获取分页数据库数据
export const getDataList = async (tabName, num, size,byName,byType) => {
let count = 0
let sql = ''
let numindex = 0
await getCount(tabName).then((resNum) => {
count = Math.ceil(resNum[0].num / size)
})
if(((num - 1) * size) == 0) {
numindex = 0
} else {
numindex = ((num - 1) * size)
}
sql = `select * from ${tabName}`
if(byName && byType) {
// desc asc
sql += ` order by ${byName} ${byType}`
}
sql += ` limit ${numindex},${size}`
console.log(sql)
if (count < num - 1) {
return new Promise((resolve, reject) => {
reject("无数据")
});
} else {
return new Promise((resolve, reject) => {
plus.sqlite.selectSql({
name: dbName,
// sql: "select * from userInfo limit 3 offset 3",
sql:sql ,
success(e) {
resolve(e);
},
fail(e) {
reject(e);
}
})
})
}
}
//查询数据库数据
export const selectDataList = (tabName,setData,byName,byType) => {
let setStr = ''
let sql = ''
if (JSON.stringify(setData) !== '{}') {
let dataKeys = Object.keys(setData)
dataKeys.forEach((item, index) => {
console.log(setData[item])
setStr += (
`${item}=${JSON.stringify(setData[item])}${dataKeys.length - 1 !== index ? " and " : ""}`)
})
sql = `select * from ${tabName} where ${setStr}`
} else {
sql = `select * from ${tabName}`
}
if(byName && byType) {
// desc asc
sql += ` order by ${byName} ${byType}`
}
console.log(sql)
if (tabName !== undefined) {
return new Promise((resolve, reject) => {
plus.sqlite.selectSql({
name: dbName,
sql: sql,
success(e) {
resolve(e);
},
fail(e) {
console.log(e)
reject(e);
}
})
})
} else {
return new Promise((resolve, reject) => {
reject("错误")
});
}
}
//查询数据库数据
export const selectBySQL = (sql) => {
console.log(sql)
return new Promise((resolve, reject) => {
plus.sqlite.selectSql({
name: dbName,
sql: sql,
success(e) {
console.log('success')
resolve(e);
},
fail(e) {
console.log(e)
reject(e);
}
})
})
}
/**
* 创建一般索引
* @param tableName 表名
* @param indexName 索引名
* @param fieldName 字段名
*/
export const createIndex = (tableName, indexName, fieldName) => {
let sql = `CREATE INDEX ${indexName} ON ${tableName} (${fieldName})`
console.log('新建索引', sql)
return new Promise((resolve, reject) => {
plus.sqlite.executeSql({
name: dbName,
sql: sql,
success(e) {
resolve(e);
},
fail(e) {
console.log(e)
reject(e);
}
})
});
}
/**
* 判断表索引是否存在
* @param tableName 表名
* @param indexName 索引名
*/
export const existsIndex = (tableName, indexName) => {
let sql = `SELECT count(*) num FROM sqlite_master WHERE type = 'index' and name = '${indexName}' and tbl_name = '${tableName}'`
console.log(tableName, indexName, sql)
return new Promise((resolve, reject) => {
plus.sqlite.selectSql({
name: dbName,
sql: sql,
success(e) {
resolve(e);
},
fail(e) {
console.log(e)
reject(e);
}
})
});
}
/**
* 判断表字段是否存在
* @param tableName 表名
* @param fieldName 字段名
*/
export const existsField = (tableName, fieldName) => {
let sql = `SELECT count(*) num FROM sqlite_master WHERE type = 'table' and name = '${fieldName}' and tbl_name = '${tableName}'`
console.log(tableName, fieldName, sql)
return new Promise((resolve, reject) => {
plus.sqlite.selectSql({
name: dbName,
sql: sql,
success(e) {
resolve(e);
},
fail(e) {
console.log(e)
reject(e);
}
})
});
}
//把这些方法导出去
export const sqlite = {
isOpen,
openDb,
createTab,dropTab,
mergeSql,
getDataList,
addTabItem,
closeSQL,
deleteInformationType,
getTable,
getCount,
updateSQL,
isTable,
selectDataList,
selectBySQL,updateBySQL,
createIndex,
existsIndex,
existsField,
};
在App.vue 文件的onLaunch: function() {} 函数中
sqlite 需要依赖存储权限,因此需要在成功获取权限后,初始化相关操作
// 判断有没有存储权限
var _this = this
plus.android.requestPermissions(['android.permission.WRITE_EXTERNAL_STORAGE'], function(e) {
console.log(e.deniedPresent)
if (e.deniedAlways.length > 0) { //权限被永久拒绝
// 弹出提示框解释为何需要读写手机储存权限,引导用户打开设置页面开启
uni.showModal({
title: '存储权限',
content: '您拒绝了存储权限,请去设置-应用开启存储权限。',
success: function (res) {
if (res.confirm) {
// console.log('用户点击确定');
} else if (res.cancel) {
// console.log('用户点击取消');
}
}
});
}
if (e.deniedPresent.length > 0) { //权限被临时拒绝
// 弹出提示框解释为何需要读写手机储存权限,可再次调用plus.android.requestPermissions申请权限
plus.android.requestPermissions(['android.permission.WRITE_EXTERNAL_STORAGE'])
// console.log('666666666 ' + e.deniedPresent.toString());
}
if (e.granted.length > 0) { //权限被允许
//调用依赖获取读写手机储存权限的代码
// _this.upload() // 获取权限成功之后调用的函数
// console.log('2222222222 ' + e.granted.toString());
if(!sqlite.isOpen()){
sqlite.openDb().then((res) => {
SysBoxDetail.init();
// ......
});
}
}
}, function(e) {
// console.log('R12133313221' + JSON.stringify(e));
});
在sqlite表的脚本文件中,已将所有函数export
在vue中,先引入相关文件,后续可以直接使用
import {SysBoxDetail} from '@/db/sqlite/boxDetail.js'
SysBoxDetail.selectAll(this.queryParams).then((res) => {
console.log(res)
})
表名
参照文章
SQLite 创建表 | 菜鸟教程