HTML5 Web SQL数据库

Posted thgj0006

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了HTML5 Web SQL数据库相关的知识,希望对你有一定的参考价值。

html5 Web SQL 数据库

Web SQL 是在浏览器上模拟数据库,可以使用 JS 来操作 SQL 完成对数据的读写。

Web SQL 数据库 API 并不是 HTML5 规范的一部分,但是它是一个独立的规范,引入了一组使用 SQL 操作客户端数据库的 APIs。

如果你是一个 Web 后端程序员,应该很容易理解 SQL 的操作。

你也可以参考我们的 SQL 教程,了解更多数据库操作知识。

Web SQL 数据库可以在最新版的 Safari, Chrome 和 Opera 浏览器中工作。


核心方法

以下是规范中定义的三个核心方法:

  1. openDatabase:这个方法使用现有的数据库或者新建的数据库创建一个数据库对象。
  2. transaction:这个方法让我们能够控制一个事务,以及基于这种情况执行提交或者回滚。
  3. executeSql:这个方法用于执行实际的 SQL 查询。

打开数据库

我们可以使用 openDatabase() 方法来打开已存在的数据库,如果数据库不存在,则会创建一个新的数据库,使用代码如下:

var db = openDatabase('mydb', '1.0', 'Test DB', 2 * 1024 * 1024);

openDatabase() 方法对应的五个参数说明:

  1. 数据库名称
  2. 版本号
  3. 描述文本
  4. 数据库大小
  5. 创建回调

第五个参数,创建回调会在创建数据库后被调用。


执行查询操作

执行操作使用 database.transaction() 函数:

var db = openDatabase('mydb', '1.0', 'Test DB', 2 * 1024 * 1024);
db.transaction(function (tx)   
   tx.executeSql('CREATE TABLE IF NOT EXISTS LOGS (id unique, log)');
);

上面的语句执行后会在 'mydb' 数据库中创建一个名为 LOGS 的表。


插入数据

在执行上面的创建表语句后,我们可以插入一些数据:

var db = openDatabase('mydb', '1.0', 'Test DB', 2 * 1024 * 1024);
db.transaction(function (tx) 
   tx.executeSql('CREATE TABLE IF NOT EXISTS LOGS (id unique, log)');
   tx.executeSql('INSERT INTO LOGS (id, log) VALUES (1, "W3Cschool教程")');
   tx.executeSql('INSERT INTO LOGS (id, log) VALUES (2, "www.w3cschool.cn")');
);

我们也可以使用动态值来插入数据:

var db = openDatabase('mydb', '1.0', 'Test DB', 2 * 1024 * 1024);
db.transaction(function (tx)   
  tx.executeSql('CREATE TABLE IF NOT EXISTS LOGS (id unique, log)');
  tx.executeSql('INSERT INTO LOGS (id,log) VALUES (?, ?)', [e_id, e_log]);
);

实例中的 e_id 和 e_log 是外部变量,executeSql 会映射数组参数中的每个条目给 "?"。


读取数据

以下实例演示了如何读取数据库中已经存在的数据:

var db = openDatabase('mydb', '1.0', 'Test DB', 2 * 1024 * 1024);

db.transaction(function (tx) 
   tx.executeSql('CREATE TABLE IF NOT EXISTS LOGS (id unique, log)');
   tx.executeSql('INSERT INTO LOGS (id, log) VALUES (1, "W3Cschool教程")');
   tx.executeSql('INSERT INTO LOGS (id, log) VALUES (2, "www.w3cschool.cn")');
);

db.transaction(function (tx) 
   tx.executeSql('SELECT * FROM LOGS', [], function (tx, results) 
      var len = results.rows.length, i;
      msg = "

查询记录条数: " + len + "

"; document.querySelector('#status').innerHTML += msg; for (i = 0; i < len; i++) alert(results.rows.item(i).log ); , null); );


完整实例

var db = openDatabase('mydb', '1.0', 'Test DB', 2 * 1024 * 1024);
var msg;

db.transaction(function (tx) 

            tx.executeSql('CREATE TABLE IF NOT EXISTS LOGS (id unique, log)');

            tx.executeSql('INSERT INTO LOGS (id, log) VALUES (1, "W3Cschool教程")');

            tx.executeSql('INSERT INTO LOGS (id, log) VALUES (2, "www.w3cschool.cn")');

            msg = '<p>数据表已创建,且插入了两条数据。</p>';

            document.querySelector('#status').innerHTML =  msg;

         );

db.transaction(function (tx) 

            tx.executeSql('SELECT * FROM LOGS', [], function (tx, results) 

               var len = results.rows.length, i;

               msg = "<p>查询记录条数: " + len + "</p>";

               document.querySelector('#status').innerHTML +=  msg;

               for (i = 0; i < len; i++)

                  msg = "<p><b>" + results.rows.item(i).log + "</b></p>";

                  document.querySelector('#status').innerHTML +=  msg;

               

            , null);

         );

尝试一下 »

以上实例运行结果如下图所示:


删除记录

删除记录使用的格式如下:

db.transaction(function (tx) 
    tx.executeSql('DELETE FROM LOGS  WHERE id=1');
);

删除指定的数据 id 也可以是动态的:

db.transaction(function(tx) 
    tx.executeSql('DELETE FROM LOGS WHERE id=?', [id]);
);

更新记录

更新记录使用的格式如下:

db.transaction(function (tx) 
    tx.executeSql('UPDATE LOGS SET log=\\'www.w3cschool.cn\\' WHERE id=2');
);

更新指定的数据 id 也可以是动态的:

db.transaction(function(tx) 
    tx.executeSql('UPDATE LOGS SET log=\\'www.w3cschool.cn\\' WHERE id=?', [id]);
);

完整实例

<!DOCTYPE HTML>
<html>
   <head>
      <meta charset="UTF-8">  
      <script type="text/javascript">
      
         var db = openDatabase('mydb', '1.0', 'Test DB', 2 * 1024 * 1024);
         var msg;
         
         db.transaction(function (tx) 
            tx.executeSql('CREATE TABLE IF NOT EXISTS LOGS (id unique, log)');
            tx.executeSql('INSERT INTO LOGS (id, log) VALUES (1, "W3Cschool教程")');
            tx.executeSql('INSERT INTO LOGS (id, log) VALUES (2, "www.w3cschool.cn")');
            msg = '<p>数据表已创建,且插入了两条数据。</p>';
            document.querySelector('#status').innerHTML =  msg;
         );

         db.transaction(function (tx) 
              tx.executeSql('DELETE FROM LOGS  WHERE id=1');
              msg = '<p>删除 id 为 1 的记录。</p>';
              document.querySelector('#status').innerHTML =  msg;
         );

         db.transaction(function (tx) 
             tx.executeSql('UPDATE LOGS SET log=\\'www.w3cschool.cn\\' WHERE id=2');
              msg = '<p>更新 id 为 2 的记录。</p>';
              document.querySelector('#status').innerHTML =  msg;
         );

         db.transaction(function (tx) 
            tx.executeSql('SELECT * FROM LOGS', [], function (tx, results) 
               var len = results.rows.length, i;
               msg = "<p>查询记录条数: " + len + "</p>";
               document.querySelector('#status').innerHTML +=  msg;
               
               for (i = 0; i < len; i++)
                  msg = "<p><b>" + results.rows.item(i).log + "</b></p>";
                  document.querySelector('#status').innerHTML +=  msg;
               
            , null);
         );
         
      </script>
      
   </head>
   
   <body>
      <div id="status" name="status">状态信息</div>
   </body>
   
</html>
	

尝试一下 »

以上实例运行结果如下图所示:

好了,学习完本节内容,你应该会对 HTML5 的 Web SQL 有不少的好感的,毕竟它拥有较大的存储空间(支持自定义),存储结构自由,并且你可以方便地使用 SQL 来进行读写!

HTML5 离线存储之Web SQL

HTML5 在离线存储之Web SQL 

本篇没有考虑异步,多线程及SQL注入

WebDatabase 规范中说这份规范不再维护了,原因是同质化(几乎实现者都选择了Sqlite), 
且不说这些,单看在HTML5中如何实现离线数据的CRUD,最基本的用法(入门级别) 
 
1,打开数据库 
2,创建表 
3,新增数据 
4,更新数据 
5,读取数据 
6,删除数据 

事实上,关键点在于如何拿到一个可执行SQL语句的上下文, 
像创建表,删除表,CRUD操作等仅区别于SQL语句的写法.OK,貌似"SqlHelper"啊,换个名字,dataBaseOperator就它了

executeReader,executeScalar两个方法与executeNonQuery严重同质,

下边的代码产生定义了我们的dataBaseOperator"类",第二行
3-5行则定义打开数据库连接方法,"类方法",效果类似C#中的静态方法,直接类名.方法调用
6-15行则定义executeNonQuery方法,意指查询数据库,与executeReader方法和executeScalar方法同质,均可返回记录集
整个 dataBaseOperator就完整了,很简单,唯一要指出的是,测试以下代码时请选择一个支持HTML5的浏览器!如Google Chrome

技术分享
1 //TODO;SQL注入
2  function dataBaseOperator() {};
3 dataBaseOperator.openDatabase = function () {
4 return window.openDatabase("dataBaseUserStories", "1.0", "dataBase used for user stories", 2 * 1024 * 1024);
5 }
6 dataBaseOperator.executeNonQuery = function (sql, parameters, callback) {
7 var db = this.openDatabase();
8 db.transaction(function (trans) {
9 trans.executeSql(sql, parameters, function (trans, result) {
10 callback(result);
11 }, function (trans, error) {
12 throw error.message;
13 });
14 });
15 }
16 dataBaseOperator.executeReader = dataBaseOperator.executeNonQuery;
17 dataBaseOperator.executeScalar = dataBaseOperator.executeNonQuery;
技术分享

有了"SqlHeper",再看业务处理层(Business Logic Layer)
业务处理类包括了创建表,删除表,新增记录,删除记录以及读取记录,这里没有写更新,实际上先删后增一样滴,即使要写也不复杂 

技术分享
1 function userStoryProvider() {
2 this.createUserStoryTable = function () {
3 dataBaseOperator.executeNonQuery("CREATE TABLE tbUserStories(id integer primary key autoincrement,role,ability,benefit,name,importance,estimate,notes)");
4 };
5 this.dropUserStoryTable = function () {
6 dataBaseOperator.executeNonQuery("DROP TABLE tbUserStories");
7 };
8 this.addUserStory = function (role, ability, benefit, name, importance, estimate, notes) {
9 dataBaseOperator.executeNonQuery("INSERT INTO tbUserStories(role,ability,benefit,name,importance,estimate,notes) SELECT ?,?,?,?,?,?,?",
10 [role, ability, benefit, name, importance, estimate, notes], function (result) {
11 //alert("rowsAffected:" + result.rowsAffected);
12   });
13 };
14 this.removeUserStory = function (id) {
15 dataBaseOperator.executeNonQuery("DELETE FROM tbUserStories WHERE id = ?", [id], function (result) {
16 //alert("rowsAffected:" + result.rowsAffected);
17   });
18 };
19 this.loadUserStories = function (callback) {
20 dataBaseOperator.executeReader("SELECT * FROM tbUserStories", [], function (result) {
21 callback(result);
22 });
23 //result.insertId,result.rowsAffected,result.rows
24   };
25 }
技术分享

createUserStoryTable,dropUserStoryTable,addUserStory,removeUserStory又是严重同质,不说了,仅SQL语句不同而已

但loadUserStories与上述四个方法均不同,是因为它把SQLResultSetRowList返回给了调用者,这里仍然是简单的"转发",
 页面在使用的时候需要首先创建provider实例(使用类似C#中的类实例上的方法调用)

1 var _userStoryProvider = new userStoryProvider();

之后就可以调用该实例的方法了,仅举个例子,具体代码省去

技术分享
function loadUserStory() {
try {
_userStoryProvider.loadUserStories(function (result) {
var _userStories = new Array();
for (var i = 0; i < result.rows.length; i++) {
var o = result.rows.item(i);
var _userStory = new userStory(o.id, o.name, o.role, o.ability, o.benefit, o.importance, o.estimate, o.notes);
_userStories.push(_userStory);
}
//...
} catch (error) {
alert("_userStoryProvider.loadUserStories:" + error);
}
}
技术分享

得到_userStories这个数组后,就没有下文了,是自动创建HTML还是绑定到EXT,发挥想象力吧...继续

userStory是一个自定义的"Model" "类"

技术分享
1 function userStory(id, name, role, ability, benefit, importance, estimate, notes) {
2 this.id = id;
3 this.name = name;
4 this.role = role;
5 this.ability = ability;
6 this.benefit = benefit;
7 this.importance = importance;
8 this.estimate = estimate;
9 this.notes = notes;
10 };
技术分享

最后贴出应用的代码,业务相关的代码,不看也罢,谁家与谁家的都不同

技术分享
1 /*
2 http://stackoverflow.com/questions/2010892/storing-objects-in-html5-localstorage
3 http://www.w3.org/TR/webdatabase/#sqlresultset
4 http://html5doctor.com/introducing-web-sql-databases/
5 http://stackoverflow.com/questions/844885/sqlite-insert-into-with-unique-names-getting-id
6  */
7  var _userStoryProvider = new userStoryProvider();
8 $(document).ready(function () {
9 loadUserStory();
10
11 /* 添加用户故事 */
12 $("#btnAdd").click(function () {
13 var item = { role: $("#role").val(), ability: $("#ability").val(), benefit: $("#benefit").val(), name: $("#Name").val(), importance: $("#Importance").val(), estimate: $("#Estimate").val(), notes: $("#Notes").val() };
14 try {
15 _userStoryProvider.addUserStory(item.role, item.ability, item.benefit, item.name, item.importance, item.estimate, item.notes);
16 loadUserStory();
17 } catch (error) {
18 alert("_userStoryProvider.addUserStory:" + error);
19 }
20 });
21
22 /* 创建用户故事表 */
23 $("#btnCreateTable").click(function () {
24 try {
25 _userStoryProvider.createUserStoryTable();
26 } catch (error) {
27 alert("_userStoryProvider.createUserStoryTable:" + error);
28 }
29 });
30
31 /* 删除用户故事表 */
32 $("#btnDropTable").click(function () {
33 try {
34 _userStoryProvider.dropUserStoryTable();
35 } catch (error) {
36 alert("_userStoryProvider.dropUserStoryTable:" + error);
37 }
38 });
39 });
40
41  /* 加载用户故事 */
42 function loadUserStory() {
43 try {
44 _userStoryProvider.loadUserStories(function (result) {
45 var _userStories = new Array();
46 for (var i = 0; i < result.rows.length; i++) {
47 var o = result.rows.item(i);
48 var _userStory = new userStory(o.id, o.name, o.role, o.ability, o.benefit, o.importance, o.estimate, o.notes);
49 _userStories.push(_userStory);
50 }
51
52 if (!_userStories) return;
53 var table = document.getElementById("user_story_table");
54 if (!table) return;
55 var _trs = table.getElementsByTagName("tr");
56 var _len = _trs.length;
57 for (var i = 0; i < _len; i++) {
58 table.removeChild(_trs[i]);
59 }
60 {
61 var tr = document.createElement("tr");
62 tr.setAttribute("class", "product_backlog_row header");
63 {
64 tr.appendChild(CreateTd("id", "id"));
65 tr.appendChild(CreateTd("name", "name"));
66 tr.appendChild(CreateTd("importance", "importance"));
67 tr.appendChild(CreateTd("estimate", "estimate"));
68 tr.appendChild(CreateTd("description", "role"));
69 tr.appendChild(CreateTd("notes", "notes"));
70 tr.appendChild(CreateTd("delete", "delete"));
71 };
72 table.appendChild(tr);
73 }
74 for (var i = 0; i < _userStories.length; i++) {
75 CreateRow(table, _userStories[i]);
76 }
77 });
78 } catch (error) {
79 alert("_userStoryProvider.loadUserStories:" + error);
80 }
81 }
82 function CreateRow(table, userStory) {
83 if (!table) return;
84 if (!userStory) return;
85 {
86 var tr = document.createElement("tr");
87 tr.setAttribute("class", "product_backlog_row");
88 {
89 tr.appendChild(CreateTd("id", userStory.id));
90 tr.appendChild(CreateTd("name", userStory.name));
91 tr.appendChild(CreateTd("importance", userStory.importance));
92 tr.appendChild(CreateTd("estimate", userStory.estimate));
93 tr.appendChild(CreateTd("description", userStory.role));
94 tr.appendChild(CreateTd("notes", userStory.notes));
95 tr.appendChild(CreateDeleteButton("delete_button", userStory.id));
96 };
97 table.appendChild(tr);
98 }
99 }
100 function CreateTd(name, value) {
101 var td = document.createElement("td");
102 td.setAttribute("class", "user_story " + name);
103 td.innerText = value;
104 return td;
105 };
106 function CreateDeleteButton(name, id) {
107 var td = document.createElement("td");
108 td.setAttribute("class", "user_story " + name);
109 /* 删除用户故事 */
110 td.innerHTML = "<a href=\"###\" title=\"delete\" onclick=\"javascript:_userStoryProvider.removeUserStory(\‘" + id + "‘);removeRow(this);\">>>delete</a>";
111 return td;
112 }
113 function removeRow(obj) {
114 document.getElementById("user_story_table").deleteRow(obj.parentNode.parentNode.rowIndex);
115 //obj.parentNode.parentNode.removeNode(true);
116 }
技术分享

 

有一个小例子,点这里下载(占位,有点小毛病改好就放)

看完代码复习下基本功课

1,WindowDatabase接口,注意openDatabase方法

 

技术分享
[Supplemental, NoInterfaceObject]
interface WindowDatabase {
Database openDatabase(in DOMString name, in DOMString version, in DOMString displayName, in unsigned long estimatedSize, in optional DatabaseCallback creationCallback);
};
Window implements WindowDatabase;

[Supplemental, NoInterfaceObject]
interface WorkerUtilsDatabase {
Database openDatabase(in DOMString name, in DOMString version, in DOMString displayName, in unsigned long estimatedSize, in optional DatabaseCallback creationCallback);
DatabaseSync openDatabaseSync(in DOMString name, in DOMString version, in DOMString displayName, in unsigned long estimatedSize, in optional DatabaseCallback creationCallback);
};
WorkerUtils implements WorkerUtilsDatabase;

[Callback=FunctionOnly, NoInterfaceObject]
interface DatabaseCallback {
void handleEvent(in Database database);
};
技术分享

2,SQLTransaction接口,关注executeSql方法

技术分享
typedef sequence<any> ObjectArray;

interface SQLTransaction {
void executeSql(in DOMString sqlStatement, in optional ObjectArray arguments, in optional SQLStatementCallback callback, in optional SQLStatementErrorCallback errorCallback);
};

[Callback=FunctionOnly, NoInterfaceObject]
interface SQLStatementCallback {
void handleEvent(in SQLTransaction transaction, in SQLResultSet resultSet);
};

[Callback=FunctionOnly, NoInterfaceObject]
interface SQLStatementErrorCallback {
boolean handleEvent(in SQLTransaction transaction, in SQLError error);
};
技术分享

3,最后看下SQLResultSetRowList定义

interface SQLResultSetRowList {
readonly attribute unsigned long length;
getter any item(in unsigned long index);
};

和SQLResultSet定义

1 interface SQLResultSet {
2 readonly attribute long insertId;
3 readonly attribute long rowsAffected;
4 readonly attribute SQLResultSetRowList rows;
5 };

类图
技术分享
由于window对象实现了WindowDatabase接口,从而可以直接在window对象上调用openDatabase等方法
同时实现WindowDatabse接口的还有WorkerUtils对象

以上是关于HTML5 Web SQL数据库的主要内容,如果未能解决你的问题,请参考以下文章

HTML5 Web SQL DB - 最大表大小?

Web 浏览器中的 SQL 数据库存储 Javascript/HTML5

HTML5 Web SQL 数据库简介

HTML5 离线存储之Web SQL

HTML5 IndexedDB、Web SQL 数据库和浏览器大战

HTML5中Web Sql学后总结