概述
App Inventor内置的TinyDB是简单的键值存储,不支持复杂查询。SQLite扩展提供完整的SQL数据库能力。
已有文档:extensions/SQLite.md 介绍了SQLite扩展。db.md 介绍了TinyDB和TinyWebDB。本文聚焦SQLite实战用法。
TinyDB vs SQLite
| 特性 | TinyDB | SQLite |
|---|---|---|
| 存储方式 | 键值对 | 关系型表 |
| 查询 | 只能按Key | SQL查询 |
| 数据量 | 小 | 大 |
| 排序/过滤 | 手动实现 | SQL语句 |
| 多表 | ❌ | ✅ |
| 聚合统计 | 手动 | SQL聚合函数 |
| 适合场景 | 简单配置 | 结构化数据 |
SQLite扩展
导入
- 下载SQLite扩展.aix文件
- Designer → Extension → Import Extension
核心方法
| 方法 | 说明 |
|---|---|
| OpenDatabase(dbName) | 打开/创建数据库 |
| ExecuteSQL(sql) | 执行SQL语句 |
| QuerySQL(sql) | 查询并返回结果 |
| CloseDatabase() | 关闭数据库 |
事件
| 事件 | 参数 | 说明 |
|---|---|---|
| OnResult(result) | 查询结果 | 查询返回 |
| OnError(error) | 错误信息 | 执行出错 |
基本操作
创建数据库和表
当 Screen1.初始化
调用 SQLite1.打开数据库("myapp.db")
' 创建用户表
设 建表SQL = "CREATE TABLE IF NOT EXISTS users (" &
"id INTEGER PRIMARY KEY AUTOINCREMENT, " &
"name TEXT NOT NULL, " &
"phone TEXT, " &
"email TEXT, " &
"created_at DATETIME DEFAULT CURRENT_TIMESTAMP)"
调用 SQLite1.执行SQL(建表SQL)
插入数据
当 按钮_添加用户.被点击
设 SQL = "INSERT INTO users (name, phone, email) VALUES ('" &
输入框_姓名.文本 & "', '" &
输入框_电话.文本 & "', '" &
输入框_邮箱.文本 & "')"
调用 SQLite1.执行SQL(SQL)
标签_状态.文本 = "✅ 用户已添加"
参数化查询(防SQL注入)
当 按钮_安全添加.被点击
设 SQL = "INSERT INTO users (name, phone, email) VALUES (?, ?, ?)"
调用 SQLite1.执行参数化SQL(SQL,
[输入框_姓名.文本, 输入框_电话.文本, 输入框_邮箱.文本])
查询数据
当 按钮_查询全部.被点击
调用 SQLite1.查询SQL("SELECT * FROM users ORDER BY created_at DESC")
当 SQLite1.查询结果(结果)
' 结果是列表,每项是一个字典
设 显示 = ""
设 i = 1
当 i ≤ 列表长度(结果)
设 记录 = 列表第i项(结果)
设 显示 = 显示 &
从字典 记录 获取 "name" & " | " &
从字典 记录 获取 "phone" & " | " &
从字典 记录 获取 "email" & "\n"
设 i = i + 1
标签_用户列表.文本 = 显示
条件查询
当 按钮_搜索.被点击
设 SQL = "SELECT * FROM users WHERE name LIKE '%" & 输入框_搜索.文本 & "%'"
调用 SQLite1.查询SQL(SQL)
更新数据
当 按钮_更新.被点击
设 SQL = "UPDATE users SET phone = '" & 输入框_新电话.文本 &
"' WHERE name = '" & 输入框_姓名.文本 & "'"
调用 SQLite1.执行SQL(SQL)
删除数据
当 按钮_删除.被点击
设 SQL = "DELETE FROM users WHERE id = " & 选中ID
调用 SQLite1.执行SQL(SQL)
实战案例:学生成绩管理
创建表结构
当 Screen1.初始化
调用 SQLite1.打开数据库("school.db")
调用 SQLite1.执行SQL(
"CREATE TABLE IF NOT EXISTS students (" &
"id INTEGER PRIMARY KEY AUTOINCREMENT, " &
"name TEXT NOT NULL, " &
"class TEXT, " &
"student_no TEXT UNIQUE)")
调用 SQLite1.执行SQL(
"CREATE TABLE IF NOT EXISTS scores (" &
"id INTEGER PRIMARY KEY AUTOINCREMENT, " &
"student_id INTEGER, " &
"subject TEXT, " &
"score REAL, " &
"exam_date TEXT, " &
"FOREIGN KEY(student_id) REFERENCES students(id))")
录入成绩
当 按钮_录入.被点击
' 先查找学生ID
设 查询SQL = "SELECT id FROM students WHERE name = '" & 输入框_学生.文本 & "'"
调用 SQLite1.查询SQL(查询SQL)
当 SQLite1.查询结果(结果)
如果 列表长度(结果) > 0
设 学生ID = 从字典 列表第1项(结果) 获取 "id"
设 录入SQL = "INSERT INTO scores (student_id, subject, score, exam_date) VALUES (" &
学生ID & ", '" & 下拉框_科目.选中项 & "', " &
输入框_分数.文本 & ", '" &
Clock1.格式化日期时间(Clock1.当前时间(), "yyyy-MM-dd") & "')"
调用 SQLite1.执行SQL(录入SQL)
标签_状态.文本 = "✅ 成绩已录入"
统计查询
' 查询某学生所有成绩
设 SQL = "SELECT s.name, sc.subject, sc.score, sc.exam_date " &
"FROM scores sc JOIN students s ON sc.student_id = s.id " &
"WHERE s.name = '" & 输入框_学生.文本 & "' " &
"ORDER BY sc.exam_date DESC"
' 查询某科目平均分
设 SQL = "SELECT subject, AVG(score) as avg_score, MAX(score) as max_score, " &
"MIN(score) as min_score, COUNT(*) as count " &
"FROM scores WHERE subject = '" & 下拉框_科目.选中项 & "' " &
"GROUP BY subject"
' 班级成绩排名
设 SQL = "SELECT s.name, s.class, SUM(sc.score) as total " &
"FROM scores sc JOIN students s ON sc.student_id = s.id " &
"GROUP BY sc.student_id ORDER BY total DESC"
用ListView展示查询结果
当 SQLite1.查询结果(结果)
设 显示列表 = 创建空列表
设 i = 1
当 i ≤ 列表长度(结果)
设 记录 = 列表第i项(结果)
设 显示文本 = 从字典 记录 获取 "name" & " | " &
从字典 记录 获取 "subject" & " | " &
从字典 记录 获取 "score" & "分"
设 显示列表 = 添加列表项(显示列表, 显示文本)
设 i = i + 1
设 ListView1.元素 = 显示列表
与已有文档的关系
| 技术 | 已有文档 | SQLite场景用途 |
|---|---|---|
| TinyDB | db.md |
简单配置仍用TinyDB |
| Web API | api_communication.md |
数据同步到云端 |
| ListView | listview_custom.md |
展示查询结果 |
| CSV导出 | file_operations.md |
导出SQLite数据 |
| JSON解析 | json_parse.md |
解析API返回数据 |
常见问题
Q1: SQLite数据库文件在哪里?
数据库文件存储在应用的私有目录:/data/data/包名/databases/。需要root权限才能直接访问。
Q2: 如何导出SQLite数据?
查询全部数据 → 转CSV → 保存到/sdcard/:
当 按钮_导出.被点击
调用 SQLite1.查询SQL("SELECT * FROM users")
当 SQLite1.查询结果(结果)
设 CSV = "id,name,phone,email\n"
设 i = 1
当 i ≤ 列表长度(结果)
设 r = 列表第i项(结果)
设 CSV = CSV & 从字典r获取"id" & "," &
从字典r获取"name" & "," &
从字典r获取"phone" & "," &
从字典r获取"email" & "\n"
设 i = i + 1
调用 File1.保存文件(CSV, "/sdcard/MyApp/export.csv")
Q3: 数据库占用空间大?
-- 清理碎片
VACUUM;
-- 删除旧数据
DELETE FROM scores WHERE exam_date < '2025-01-01';
总结
| 操作 | SQL |
|---|---|
| 建表 | CREATE TABLE |
| 插入 | INSERT INTO |
| 查询 | SELECT |
| 条件 | WHERE |
| 排序 | ORDER BY |
| 聚合 | AVG/SUM/COUNT/MAX/MIN |
| 关联 | JOIN |
| 分组 | GROUP BY |
版权声明:MIT App Inventor 官方文档采用 CC BY-SA 4.0 授权,本文档由 ai2claw 🐝 整理。
扫码添加客服咨询