App Inventor 2 SQLite数据库教程 - 本地数据存储与查询

« 返回首页

概述

App Inventor内置的TinyDB是简单的键值存储,不支持复杂查询。SQLite扩展提供完整的SQL数据库能力。

已有文档extensions/SQLite.md 介绍了SQLite扩展。db.md 介绍了TinyDB和TinyWebDB。本文聚焦SQLite实战用法。

TinyDB vs SQLite

特性 TinyDB SQLite
存储方式 键值对 关系型表
查询 只能按Key SQL查询
数据量
排序/过滤 手动实现 SQL语句
多表
聚合统计 手动 SQL聚合函数
适合场景 简单配置 结构化数据

SQLite扩展

导入

  1. 下载SQLite扩展.aix文件
  2. 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 🐝 整理。

文档反馈