Cordova 的本地 SQLite 需要原生插件支持。引入 cordova.js 并不意味着普通浏览器已经具有数据库插件,调用前应等待 deviceready。

下面使用 cordova-sqlite-storage 的对象参数入口演示基本流程;插件、Cordova 平台和运行系统仍须按项目锁定版本。插件维护方说明

打开、写入与读取

示例使用独立的学习数据库,不应直接指向业务库:

document.addEventListener('deviceready', function () {
  var db = window.sqlitePlugin.openDatabase({
    name: 'sqlite-learning.db',
    location: 'default'
  }, function () {
    db.transaction(function (tx) {
      tx.executeSql(
        'CREATE TABLE IF NOT EXISTS notes ' +
        '(id INTEGER PRIMARY KEY, body TEXT NOT NULL)',
        []
      );
      tx.executeSql(
        'INSERT INTO notes (body) VALUES (?)',
        ['一条学习记录']
      );
      tx.executeSql(
        'SELECT id, body FROM notes ORDER BY id',
        [],
        function (tx, result) {
          for (var i = 0; i < result.rows.length; i++) {
            console.log(result.rows.item(i).body);
          }
        }
      );
    }, function (error) {
      console.error('事务失败', error.message);
    }, function () {
      console.log('事务完成');
    });
  }, function (error) {
    console.error('打开数据库失败', error.message);
  });
}, false);

占位符 ? 与参数数组将数据交给数据库绑定,避免把用户输入直接拼接进 SQL。表名和排序列等结构部分不能用这种值占位符任意替换。

该例每次执行都会新增一条记录;CREATE TABLE IF NOT EXISTS 也不是完整的数据库升级机制。正式应用应独立设计初始化、版本迁移和重复执行策略。

结果对象分别表示什么

SELECT 返回的 rows 有 length,并通过 rows.item(i) 读取行。访问第一行之前检查 length,没有结果时不要继续取字段;需要顺序时明确写 ORDER BY。

rowsAffected 表示受语句影响的行数;insertId 在适用的插入场景才有意义。不要把查询结果行数、修改行数和新插入 ID 混为一谈。

SQL 成功还不是事务提交成功

某条 INSERT 的回调发生后,后续语句仍可能失败。因此,整体成功提示应放在事务完成回调,而不是一条语句的成功回调中。打开失败、语句失败与事务失败也应分别记录。

不要为了让演示每次输出相同,就在应用启动时 DROP TABLE;也不要用 document.write 更新已加载的页面。数据库操作和界面渲染分开处理,更容易测试空结果、回滚与重复启动。