最近公司系统需要做一个app,经过调查研究,决定用html5 + phonegap技术来开发,一方面对于html5技术已经很熟悉(虽然之前android也有所研究,但是还是在html5方面倾注精力更多),而且公司的项目pc端本身就是B/S的,移植到手机端比较容易,研发成本也比较低;另外基于html5技术的开发,可以做到跨平台,同时跑在android 和iOS两大系统没有问题。
app需要用到一些前端存储,而且是关系型数据存储的需求,当然用phonegap的机制,可以调用native的存储,不过实现起来很麻烦;所以就考虑用html5的前端离线存储,前端离线存储目前支持 Cookie、localStorage、sessionStorage、IndexedDB、Web SQL Database以及FileSystem.
Cookie就不用说,用起来超级麻烦,而且限制极大;不适合。
sessionStorage其实算不上离线存储,因为网页关闭了,存储就会丢弃。
localStorage可以做key value 的存储,对于需要有些关系处理的数据,需要自己做逻辑处理,比较麻烦。
IndexedDB其实就是前段的nosql数据库。
比较靠谱的是websql和IndexedDB,不过由于需要关系数据库的原因,选择了websql,不过IndexedDB也是一个不错的选择,后面有机会写写这块。
需要注意的是,HTML5已经会放弃Web SQL Database
放弃的原因如下:
This document was on the W3C Recommendation track but specification work has stopped. The specification reached an impasse: all interested implementors have used the same SQL backend (Sqlite), but we need multiple independent implementations to proceed along a standardisation path.
大概意思是:
该文件是W3C推荐标准,但规范的制定工作已经停止。该规范陷入僵局:所有感兴趣的实现者都使用了相同的SQL后端(SQLite的),但我们需要多个独立的实现沿着规范化的路径进行。
翻译参考:http://www.zhihu.com/question/41951041
有关标准参考: https://www.w3.org/TR/webdatabase/
关于这一点,我觉得一方面我们的app是验证型的,并不是正式需要发布的,所以选择websql没有什么后顾之忧,另外,我觉得,浏览器厂商就算以后不再改进websql,把现有的websql功能去掉的可能性不是很大,而目前的功能也满足需求了。
websql是很久的技术了,很早关注过,不过一直没用,最近想用,搜索了下,网上关于websql的文章已经很多,但是发现大部分文章都是抄来抄去的;可能很多东西大家也没有试验,就抄袭了过来;正好自己用到了相关的知识,就来个比较全面的整理。
如果你掌握过mysql,orancle,mssql等关系型数据库,对于websql的理解还是比较容易的。
websql的关键技术点分为:
- 测试浏览器支持
- 创建数据库
- 创建表格
插入数据等
用到的几个核心方法:
openDatabase openDatabaseSycn 创建数据库
- transaction起事务
- executeSql执行sql语句
测试浏览器支持
if(window.openDatabase){
console.log(“浏览器支持DataBase”);
}
创建数据库
在window对象上,有一个openDatabase方法,可以创建数据库,参考标准
Database openDatabase(in DOMString name, in DOMString version, in DOMString displayName, in unsigned long estimatedSize, in optional DatabaseCallback creationCallback);
var test_db = window.openDatabase('test', '1.0', 'Test DB', 2 * 1024 * 1024);
openDatabase共四个参数,第一个参数数据库名,第二个参数数据库版本号,第三个描述,第四个估计大小,四个参数都必须输入,但是最后一个参数可以输入null,最终创建的对象如下:
可以看出db对象上面有changeVersion方法可以改变版本号,.version可以获取版本号,transaction方法可以起事务,readTransaction方法起一个只读的事务,参考标准
For the transaction() method, the mode must be read/write. For the readTransaction() method, the mode must be read-only.
其实标准里面还有个openDatabaseSync方法,但是测试发现并没有实现【测试chrome,safari】
openDatabase还有第5个参数creationCallback,可选择的;但是测试发现如果加入了callback参数,创建的database的版本号就总是为空。
起数据库事务
从前面的图片中可以看到,有两个事务的方法,一个transaction,一个readTransaction, 两个方法均是异步的,通过传递一个callback来执行后续操作
test_db.transaction(function(tx){console.log(tx);})
回调函数会被传入一个SQLTransaction对象,该对象可以执行executeSql方法。
执行SQL语句
执行sql语句和一般的关系型数据库类似,不同的是,websql支持的数据类型 函数 等都相当有限。
executeSql支持四个参数,sql语句,sql参数,成功回调函数,错误回调函数,回调函数第一个参数是transaction,第二个是执行结果;错误回调函数第一个参数是transaction,第二个参数是错误。
创建一个数据表
var success = function(tx,results){
console.log(results);
};
var error = function(tx, err){
console.log(error);
};
var sql = 'CREATE TABLE foo (id unique, text)';
test_db.transaction(function(tx){
tx.executeSql(sql,[],success,error);
});
可以看出不需要指定字段的类型,unique表示唯一,其实也可以指定类型,但是测试发现其实指定了也没什么用,如下指定todo类型为TEXT,added_on 为DATETIME,但是在后面可以插入任意类型数据,不起约束左右;另外看有的文章说不支持自增长,测试发现是可以的。【只是在pc上测试了chrome和safari,未测试移动端的情况】【后来在移动端测试也可以】
tx.executeSql("CREATE TABLE IF NOT EXISTS " +
"todo(ID INTEGER PRIMARY KEY ASC, todo TEXT, added_on DATETIME)", [],success,error);
插入数据
test_db.transaction(function(tx){
tx.executeSql('INSERT INTO foo (id, text) VALUES (1, "test")',[],success,error);
});
查询数据
tx.executeSql('SELECT * FROM foo', [], function (tx, results) {
var len = results.rows.length, i;
for (i = 0; i < len; i++) {
alert(results.rows.item(i).text);
}
});
查询的数据格式标准如下,通过rows.item()可以访问数据
interface SQLResultSet {
readonly attribute long insertId;
readonly attribute long rowsAffected;
readonly attribute SQLResultSetRowList rows;
};
参考: https://www.w3.org/TR/webdatabase/#sqlresultset
删除数据
test_db.transaction(function(tx){
tx.executeSql("DELETE FROM todo foo ID=?", [id],success,error);
});
支持浏览器情况
firefox 不支持,IE edge 一贯作风不支持; chrome Safari支持,移动端android iOS支持的都很不错,
具体参考 http://caniuse.com/#feat=sql-storage
使用场景
有本地存储需求的应用,比如开发一个本地存储的web端游戏;
如果开发基于html5技术的手机app,也可以考虑用websql做本地存储,不过由于前面提到的原因,如果你的app考虑长远发展,建议使用IndexedDB。
参考文档
更多资料可以查询
https://www.w3.org/TR/webdatabase/
http://www.tutorialspoint.com/html5/html5_web_sql.htm
http://html5doctor.com/introducing-web-sql-databases/
http://www.html5rocks.com/en/tutorials/webdatabase/todo/
https://developer.tizen.org/dev-guide/2.4/org.tizen.tutorials/html/web/w3c/storage/websql_tutorial_w.htm