更新记录

0.5.1(2025-08-29)

文档修正

0.5.0(2025-08-29)

初始发布 v0.5.0


平台兼容性

云端兼容性

阿里云 腾讯云 支付宝云

uni-app x(4.75)

Chrome Safari Android iOS 鸿蒙 微信小程序
× × 8.0 × 12 ×

其他

多语言 暗黑模式 宽屏模式
× ×

bsx-sqlite

关于

一款支持鸿蒙NEXT 5.0+ 和Aandroid 8+的sqlite操作API插件(uniapp x)

初衷

由于作者本人项目,需要建一个本地单词字典数据库,使用SQLITE操作。故开发该API 以支持Android和鸿蒙NEXT。现将,API作为插件提供给大家。 作者能力有限,不足之处,请包涵。

说明

  1. 支持android 8+ (api 26+)、HarmonyOS Next 5.0+ (api 12+)
  2. 暂未支持加密
  3. HarmonyOS next暂不支持子线程,android端可自行使用官方的派发线程api执行相关操作
  4. 均使用sqlite3 wal模式
  5. delete和update操作row时需注意指定操作的行(一般指定为条件为主键对应的记录),即谓词条件;避免更新或删除非预想的记录
  6. 注意! 数据脚本,包括表名\SQL语句等是不区分大小写的. 数据库文件是区分大小写的! (app.db 和APP.db 不一样)
  7. 备份和恢复数据时的文件,可自行管理文件版本,本API不涉及;备份或恢复切勿输入错误的数据文件名!默认备份文件统一添加了_backup字符结尾
  8. 默认数据库文件都是在应用沙盒目录的数据根目录(databases)下, 暂不支持自定义路径(需求量小). 如果需要持久保留,建议自行备份到云端
  9. 批次SQL(增、删、改)支持事务;Android 支持冲突模式.
  10. 暂未处理Uint8Array类型,即不支持二进制数据操作。暂请勿用
  11. 实例注意事项:使用完必需关闭数据库连接,避免资源溢出。每个bsxsqlite实例包含一个连接,也可以定义 一个全局操作对象。无论如何必需显示关闭连接!

类型

// 用于操作查询的参数类型
type SqlSelectParmType = number | string | boolean | null
// 用于操作数据的值类型
type ValueType = number | string | Uint8Array | boolean | null
type ValueContent = Map<string, ValueType>
type ConflictResolution = 'ON_CONFLICT_NONE' | 'ON_CONFLICT_ROLLBACK' | 'ON_CONFLICT_ABORT' | 'ON_CONFLICT_FAIL' | 'ON_CONFLICT_IGNORE' | 'ON_CONFLICT_REPLACE'
type TransationExecuteObj = {
    sql: string
    args: Array<ValueType> | null
}
class BsxSqlite {
    ...
}

使用

<template>
    <view class="mx-3 flex-column">
        <scroll-view scroll-y="true" class="border border-1 p-2" style="height: 150;">
            <view v-for="user in userTable" class="flex-row justify-content-between align-content-center mb-1">
                <text class="p-1">
                    id:{{ user.id }},{{user.name}},{{user.age}},{{user.enable}},{{user.address}}
                </text>
                <view class="p-1 flex-row">
                    <text class="me-4" @tap="execute('update', user.id)">update</text>
                    <text class="" @tap="execute('delete', user.id)">delete</text>
                </view>
            </view>
        </scroll-view>

        <view class="flex-row flex-wrap mt-3">
            <button class="w-45 me-2 mb-2" @tap="execute('query')">查询</button>
            <button class="w-45 me-2 mb-2" @tap="execute('createTB')">表创建</button>
            <button class="w-45 me-2 mb-2" @tap="execute('deleteTB')">Delete表重置</button>
            <button class="w-45 me-2 mb-2" @tap="execute('dropTB')">Drop表删除</button>
            <button class="w-45 me-2 mb-2" @tap="execute('insert')">新增</button>
            <button class="w-45 me-2 mb-2" @tap="execute('insertBatch')">批量新增</button>
            <button class="w-45 me-2 mb-2" @tap="execute('transation')">事务执行SQL</button>
            <button class="w-45 me-2 mb-2" @tap="open">打开连接</button>
            <button class="w-45 me-2 mb-2" @tap="close">关闭连接</button>
            <button class="w-45 me-2 mb-2" @tap="backup">备份数据库</button>
            <button class="w-45 me-2 mb-2" @tap="restore">恢复数据库</button>
        </view>
    </view>

    <scroll-view class="mx-5 mt-3 flex-column" style="height:220;">
        <text v-for="item in message">
            {{ item }}
        </text>
    </scroll-view>
</template>

<script setup>
    import { BsxSqlite, SqlSelectParmType, ValueType, ValueContent, TransationExecuteObj } from '@/uni_modules/bsx-sqlite'
    type user = {
        id : number
        name : string
        age : number
        enable : boolean | number
        address : string | null
    }
    const dbDomain = ref<BsxSqlite | null>(null)
    const message = ref<string[]>([])
    const userTable = ref<user[]>([])

    onReady(() => {
        dbDomain.value = new BsxSqlite('app.db', 1)
        dbDomain.value?.openDb().then(() => {
            message.value.unshift('-- db is opened --')
        })
    })

    const randomName = (len : number) : string => {
        const strs = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz';
        let result = '';
        for (let i = 0; i < len; i++) {
            result += strs.charAt(Math.floor(Math.random() * strs.length))
        }
        return result;
    }

    const refresh = async () => {
        const ret : UTSJSONObject = await dbDomain.value?.query("SELECT * FROM Users")!
        console.log('--- userTable.value ---', ret)
        try {
            const dataStr = JSON.stringify(ret!['data'])
            userTable.value = JSON.parseArray<user>(dataStr!)!
        } catch (err) {
            console.log('--- 刷新数据异常 -----', err)
        }
    }
    async function execute(key : string, _id : number = -1) {
        let ret = {} as UTSJSONObject
        if (key == 'createTB') {
            ret = await dbDomain.value?.createTable("CREATE TABLE IF NOT EXISTS Users (id INTEGER PRIMARY KEY, name TEXT not null, age INTEGER DEFAULT 0 not null, enable BOOLEAN DEFAULT false, address TEXT DEFAULT null)")!
        }
        if (key == 'dropTB') {
            ret = await dbDomain.value?.executeSql("DROP TABLE Users")!
        }
        if (key == 'insert') {
            let insertData : Map<string, ValueType> = new Map();
            const newName : ValueType = randomName(6) as string
            insertData.set('name', newName)
            insertData.set('age', 123)
            ret = await dbDomain.value?.insert("Users", insertData as ValueContent)!
        }
        if (key == 'insertBatch') {
            let insertData1 : Map<string, ValueType> = new Map();
            let insertData2 : Map<string, ValueType> = new Map();
            const newName1 : ValueType = randomName(6) as string
            const newName2 : ValueType = randomName(6) as string
            insertData1.set('name', newName1)
            insertData1.set('age', 456)
            insertData2.set('name', newName2)
            let ary : Array<ValueContent> = []
            ary.push(insertData1, insertData2)
            ret = await dbDomain.value?.insertBatchRows("Users", ary)!
        }
        if (key == 'update') {
            let updateData : Map<string, ValueType> = new Map()
            updateData.set('age', 666)
            ret = await dbDomain.value?.update("Users", "id", _id, updateData as ValueContent)!
        }

        if (key == 'delete') {
            ret = await dbDomain.value?.delete("Users", "id", _id)!
        }
        if (key == 'query') {
            ret = await dbDomain.value?.query("SELECT * FROM Users")!
        }
        if (key == 'deleteTB') {
            ret = await dbDomain.value?.executeSqlWithTransation([
                {
                    sql: 'delete from users',
                    args: null
                },
                {
                    sql: "delete from sqlite_sequence where name = 'users'",
                    args: null
                }
            ] as Array<TransationExecuteObj>)!
        }
        if (key == 'transation') {
            // 注意!这里必需使用Any[]类型 预制事务脚本.以便兼容android和harmonyOS next
            let ary:Any[] = []
            for (let i = 0; i < 10; i++) {
                const newName : ValueType = randomName(6) as string
                // 模拟更新
                if (i == 5) {
                    ary.push({
                        sql: "update users set name = ?, age =? where id = ?",
                        args: [newName, 777, i - 2]
                    })
                } else {
                    ary.push({
                        sql: "insert into users (name, age) values (?, ?)",
                        args: [newName, 999]
                    })
                }
            }
            // 兼容android 必需类型转换
            ret = await dbDomain.value?.executeSqlWithTransation(JSON.parseArray<TransationExecuteObj>(JSON.stringify(ary)!)!)!
        }
        message.value.unshift(JSON.stringify(ret))
        await refresh()

    }
    const open = async () => {
        if (dbDomain.value == null || !dbDomain.value.isConnected()) {
            dbDomain.value = new BsxSqlite('app.db', 1)
            await dbDomain.value?.openDb()
            message.value.unshift('-- db is opened --')
        }
    }
    const close = () => {
        dbDomain.value?.closeDb().then((ret : UTSJSONObject) => {
            if (ret.getString('status') == 'success') {
                dbDomain.value = null
            }
            message.value.unshift('-- db is closed --')
        })
    }
    const backup = () => {
        // 实际的备份文件是 backupDb_backup.db
        dbDomain.value?.backup("backupDb.db").then((ret : UTSJSONObject) => {
            message.value.unshift(JSON.stringify(ret))
        })
    }
    const restore = () => {
        // 实际的恢复文件是 backupDb_backup.db
        dbDomain.value?.restore("backupDb.db").then((ret : UTSJSONObject) => {
            message.value.unshift(JSON.stringify(ret))
        })
    }
    onUnload(() => {
        dbDomain.value?.closeDb().then((res) => {
            console.log('--- onUnload -----', res)
        })
    })
</script>

<style>
</style>

tips 觉得不错请我喝杯咖啡吧~ (●'◡'●)

隐私、权限声明

1. 本插件需要申请的系统权限列表:

Android无需, 鸿蒙NEXT 基础权限,插件已声明权限: { "module": { "requestPermissions": [{ "name": "ohos.permission.GET_NETWORK_INFO", "usedScene": { "when": "inuse" }, "reason": "$string:permission_network_info_reason" // 本地resources内的字符串 }, { "name": "ohos.permission.INTERNET", // 访问网络(普通权限) "usedScene": { "when": "inuse" }, "reason": "$string:permission_internet_reason" }, { "name": "ohos.permission.FILE_ACCESS", // 访问网络(普通权限) "usedScene": { "when": "inuse" }, "reason": "$string:permission_file_access_reason" }] } }

2. 本插件采集的数据、发送的服务器地址、以及数据用途说明:

3. 本插件是否包含广告,如包含需详细说明广告表达方式、展示频率:

暂无用户评论。