最近有个项目需要使用离线存储,在没有网络的情况仍然可以使用。
在有网络的情况下,数据需要与服务器的数据库进行同步。
项目是基于Hbuilder开发的h5+应用,并不是原生开发,就不能使用sqlite。

html5中本地存储数据的有localstorage、web sql database、IndexedDB三种方式。

  • localstorage,已键值对的方式存储,只能存储字符串,各个浏览器的空间限制各不相同,基本为5M。
  • web sql database, 基于sqlite实现的结构化数据库。各个浏览器的空间限制不相同。
  • Indexed database, 以键值对的方式存储在数据库,以对象作为存储内容,没有表的形式,列是固定的。

只有web sql database合适目前项目:

  1. 存储空间限制,5M太小
  2. 数据同步,需要与服务器端的结构基本相同,方便开发
  3. 平台支持,目前APP都是ios、Android两个平台,web sql database支持较好。

web sql database

具体说明见 W3C定义
定义中提到
Beware. This specification is no longer in active maintenance and the Web Applications Working Group does not intend to maintain it further.
该项目在2010年已经停止维护。但目前的ios、Android的浏览器都已实现该功能。
具体的支持情况可以在 CANIUSE 查询

使用

创建/打开数据库

1
var db = openDatabase('db_name', '1.0.0', '数据库说明', size * 1024 * 1024, callback);

如果没有数据库,创建然后打开;有就直接打开。

  • 参数1:数据库名称
  • 参数2:数据库版本号。如果填写的版本号与当前已经存在的数据库版本号不一致,则会报错。
  • 参数3:数据库说明
  • 参数4:数据库的大小,单位为byte。
    IOS中最大只能申请到50M的空间
    Android下好像是根据存储空间来,有可能存储过多后造成卡死,待确认
  • 参数5:回调函数(非必须)。如果提供了回调函数,回调函数用以调用 changeVersion() 函数,不管给定什么样的版本号,回调函数将把数据库的版本号设置为空。如果没有提供回调函数,则以给定的版本号创建数据库
  • 返回值: Database 对象

数据库操作

transaction

transaction方法用以处理事务,当一条语句执行失败的时候,整个事务回滚。方法有三个参数

  1. 包含事务内容的一个方法
  2. 执行成功回调函数(可选)
  3. 执行失败回调函数(可选)
    1
    2
    3
    4
    5
    6
    7
    db.transaction(function (tx) {
    //执行事务内容,增删改查
    },function(tx,result){
    //成功的回调
    },function(tx,e){
    //失败的回调
    })

数据库的语句使用和sqlite一样.
User agents must implement the SQL dialect supported by Sqlite 3.6.19.

executeSql

executeSql 必须在事务中调用,用以执行SQL语句,返回结果,方法有四个参数

  1. 查询字符串
  2. 用以替换查询字符串中问号的参数
  3. 执行成功回调函数(可选)
  4. 执行失败回调函数(可选)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
db.transaction(function (tx) {
//创建表
tx.executeSql(
'create table if not exists user (id unique, name)', [],
function(tx, result) {
console.log('创建表成功');
},
function(tx, e) {
console.log('创建表失败: ' + e.message);
});
},function(tx,result){
//成功的回调
},function(tx,e){
//失败的回调
})

创建表

1
2
3
4
5
6
7
8
tx.executeSql(
'create table if not exists user (id unique, name)', [],
function(tx, result) {
console.log('创建表成功');
},
function(tx, e) {
console.log('创建表失败: ' + e.message);
});

插入数据

1
2
3
4
5
6
7
8
tx.executeSql(
'insert into user (id , name) values (1,"test_name")', [],
function(tx, result) {
console.log('插入成功');
},
function(tx, e) {
console.log('插入失败: ' + e.message);
});

批量数据插入时,不要每一个数据都写一个事务来处理,这样效率会很低。需将所有的插入操作写到同一个事务中执行,效率会提升很多。

删除数据

1
2
3
4
5
6
7
8
tx.executeSql(
'delete from user where id = 1', [],
function(tx, result) {
console.log('删除成功');
},
function(tx, e) {
console.log('删除失败: ' + e.message);
});

查询数据

1
2
3
4
5
6
7
8
9
10
11
tx.executeSql(
'select * from user where id = 1', [],
function(tx, result) {
console.log(result.rows.length);//查询到的行数。
console.log(JSON.stringify(result.rows.item(0)));//通过item下标的方式取到具体行数据

console.log('查询成功');
},
function(tx, e) {
console.log('查询失败: ' + e.message);
});

更新数据

1
2
3
4
5
6
7
8
9
tx.executeSql(
'update user set name = ? where id = 1', ['test_name'],
function(tx, result) {
console.log(result.rowsAffected);//受影响的数据行数
console.log('更新成功');
},
function(tx, e) {
console.log('更新失败: ' + e.message);
});

changeVersion

changeVersion 改变数据库的版本号,接受5个参数:

  1. 旧版本号
  2. 新版本号
  3. 执行成功回调函数(可选),参数为transaction对象,可以在此执行需要处理的sql语句
  4. 执行失败回调函数(可选)
  5. 执行成功回调函数(可选)。无参数,仅表示成功回调。
1
2
3
4
5
6
7
db.changeVersion(oldVer, newVer, function(tx){
//成功后执行sql的回调;
}, function(error) {
//失败的回调
}, function() {
//成功的回调
})

数据库需要升级时,可以通过版本号控制。

数据类型

  • 若表的列没有设置数据类型,字符串和数值不能通用查询。
    比如有个字段name的值为’1’:
    1
    'select * from table where name = 1' //不能查出name值为'1'的数据

调试

chrome中可以看到websql中的数据,并且能执行sql语句进行处理。

本文地址: http://gehaiqing.com/2017/10/11/js-websql/