Web SQL Database 与 Indexed Database

Electron使用 SQLite 在客户端开发中,无论是 PC 端,还是手机端,为了能够访问离线数据,数据经常需要保存到本地,IndexDB 可以用于存储本地数据,IndexDB 是一个对象存储,数据是以 key:value 的形式进行存储和访问的,相对于关系型数据库,访问速度快,但是结构简单。对于一些复杂的模型,多表关联关系,用 IndexDB 实现会相对复杂,需要通过查询实现。SQLite是客户端常用的文件型关系数据库,主流的移动端、桌面应用大多使用的 SQLite进行离线数据存储,例如微信。main.js 主线程。 阅读详情

Web SQL Database 和 Indexed Database 都是在客户端存储大量结构化数据的解决方案。Web SQL Database 实现了传统的基于 SQL 语句的数据库操作,而 Indexed Database 实现了 NoSQL 的存储方式。本文主要对比两者在 CRUD 操作方面的实现方法,按照本文所述读者可以详细了解两者异同。



  • expand内容

HTML5 简介

HTML 标准自 1999 年 12 月发布的 HTML 4.01 后,后继的 HTML 5 和其它标准被束之高阁,为了推动 web 标准化运动的发展,一些公司联合起来,成立了一个叫做 Web Hypertext Application Technology Working Group (Web 超文本应用技术工作组 - WHATWG) 的组织,HTML5 草案的前身名为 Web Applications 1.0,於 2004 年被 WHATWG 提出,於 2007 年被 W3C 接纳,并成立了新的 HTML 工作团队。HTML 5 的第一份正式草案已于 2008 年 1 月 22 日公布。HTML 5 有两大特点:首先,强化了 Web 网页的表现性能。其次,追加了 本地数据库等 Web 应用的功能。HTML5 规范可以参考 W3C 官方网站

Web SQL Database 和 Indexed Database 简介

Web SQL Database 介绍

Web SQL Database API 实际上未包含在 HTML 5 规范之中,它是一个独立的规范,它引入了一套使用 SQL 操作客户端数据库的 API,这些 API 有同步的,也有异步的, 同步版本的 API 只在工作线程(Worker Threads)上有用,由于并不是所有的浏览器都支持工作线程,一般情况下,都会使用异步 API。它的核心方法有三个:openDatabase,transaction 和 executeSql。 这些 API 已经被广泛的实现在了不同的浏览器里,尤其是手机端浏览器。虽然 W3C 官方在 2011 年 11 月声明已经不再维护 Web SQL Database 规范,但由于其广泛的实现程度,了解这些 API 对 Web 开发还是非常有必要的。 详细的 Web SQL Database 规范可以参考 官方网站。

Indexed Database 介绍

Indexed Database,也可简称为 IndexedDB(以前被称作 WebSimpleDB),同样是一个 Web 客户端存储结构化数据的规范,在 2009 年由 Oracle 提出。如果说 Web SQL Databae 在客户端实现了 传统的 SQL 数据库操作,那么 Indexed Database 更类似于 NoSQL 的形式来操作数据库 , 其中最重要的是 Indexed Database 不使用 SQL 作为查询语言。其数据存储可以不需要固定的表格模式,也经常会避免使用 SQL 的 JOIN 操作,并且一般具有水平可扩展性。目前 W3C 官方也把焦点 投到对 Indexed Database 规范的制定当中来,而 Microsoft 和 Mozilla 是对这个规范重要的两个推动者,Firefox 4 以上已经部分实现了 Indexed DB API,并且 IE 10 中也将实现 Indexed DB API。由于在手机等移动设备的浏览器中都没有实现 Indexed DB API,所以其还有一定的局限性,但这并 不妨碍它作为未来的 HTML5 的焦点而存在。详细的 Indexed Database 规范可以参考 官方网站。

浏览器对 Web SQL Database 和 Indexed Database 支持情况

表 1. Web SQL Databse
IE Firefox Chrome Safari Opera iOS Safari Android Browser
6.0( × ) 4.0~7.0( × ) 10.0~13.0( √ ) 3.1~3.2( √ ) 10.5~11.0( √ ) 3.2( √ ) 2.1( √ )
7.0( × ) 8.0( × ) 14.0( √ ) 4.0( √ ) 11.1( √ ) 4.0~4.1( √ ) 2.2( √ )
8.0( × ) 9.0( × ) 15.0( √ ) 5.0( √ ) 11.5( √ ) 4.2~4.3( √ ) 2.3,3.0( √ )
9.0( × ) 10.0( × ) 16.0( √ ) 5.1( √ ) 11.6( √ ) 5.0( √ ) 4.0( √ )
10.0( × ) 11.0( × ) 17.0( √ ) 6.0( √ ) 12.0( √ )    
  12.0( × ) 18.0( √ )        
表 2. Indexed Databse
IE Firefox Chrome Safari Opera iOS Safari Android Browser
6.0( × ) 4.0~7.0( √ ) 11.0~13.0( √ ) 3.1~3.2( × ) 10.5~11.0( × ) 3.2( × ) 2.1( × )
7.0( × ) 8.0( √ ) 14.0( √ ) 4.0( × ) 11.1( × ) 4.0~4.1( × ) 2.2( × )
8.0( × ) 9.0( √ ) 15.0( √ ) 5.0( × ) 11.5( × ) 4.2~4.3( × ) 2.3,3.0( × )
9.0( × ) 10.0( √ ) 16.0( √ ) 5.1( × ) 11.6( × ) 5.0( × ) 4.0( × )
10.0( √ ) 11.0( √ ) 17.0( √ )        
  12.0( √ ) 18.0( √ )        

浏览器对 Web SQL Database 和 Indexed Database 支持的更详细信息可以参考网站 When can I use...

Web SQL Database 和 Indexed Database 的 CRUD 操作

本文以网上购物中的购物车为例,在场景中,用户可以添加多个商品到购物车,并且可以在购物车中进行删除修改等操作。而购物车的数据用户希望关闭浏览器后仍然存在,以便下 次用户再次打开此网站,仍可以看到这些购物车中的商品。这个场景比较适合用客户端数据库存储购物车中的商品,因为这些商品是结构化的数据,并且购物车中可能会存在大量商品。 以下示例 code 在 Chrome 16.0 中通过测试。

1. 创建数据库以及相应的表

在 Web SQL Database 中,由于内嵌的是 SQLite 数据库,所以仍需用 SQL 语句创建表 , 而列的数据类型可以参考 SQLite 数据库支持的数据类型。 应用 Web SQL Database API 提供的 OpenDatabase 方法创建 ShoppingCartDB 数据库,并且应用传统的 CREATE TABLE SQL 句法创建 ShoppingCart 表。

清单 1. Web SQL Database 创建操作
 var dbInfo={ 
	 dbName:"ShoppingCartDB",  // 名称
    dbVersion:"0.1", // 版本
    dbDisplayName:"Shopping Cart Database", // 显示名称
    dbEstimatedSize:10*11024*1024  // 大小 (byte) 
 }; 
		
 var db; 
 function createDB(){ 
	 db = window.openDatabase(dbInfo.dbName , dbInfo.dbVersion , 
		 dbInfo.dbDisplayName , dbInfo.dbEstimatedSize); 
 } 

 function dbError(tx, error){ 
	 console.error(error); 
 } 

 function createShoppingCartTable(){ 
	 db.transaction(function(tx){ 
     tx.executeSql( 
		"CREATE TABLE IF NOT EXISTS ShoppingCart " + 
        "(Id TEXT PRIMARY KEY, Name TEXT, Price REAL,Count INTEGER,Desc TEXT)", [],
         function(){ console.log('ShoppingCart database created successfully!' ); }, 
		 dbError 
		 ); 
	 }); 
 }

在 Indexed Database 中,ObjectStore 代替了传统的表概念。每个 ObjectStore 相当于一个 key 和 value 的集合,key 相当于传统数据库表中的主键, 每个数据库可以有多个 ObjectStore。创建数据库时需要使用 Indexed Database API 的 open 方法,创建 ShoppingCartDB,并且调用 createObjectStore 方法创建 ShoppingCart ObjectStore。

清单 2. Indexed Database 创建操作
 var dbInfo={ 
	 dbName:"ShoppingCartDB",  // 名称
    dbVersion:"0.1"// 版本
 }; 
		
 var db; 
 var indexedDB = window.indexedDB || window.webkitIndexedDB; 

 if ('webkitIndexedDB' in window) { 
	 window.IDBTransaction = window.webkitIDBTransaction; 
	 window.IDBKeyRange = window.webkitIDBKeyRange; 
 } 

 function createDBAndShoppingCartTable(){ 
	 var request = indexedDB.open(dbInfo.dbName); 
	 request.onsuccess = function(evt) { 
		 db = evt.target.result; 
		 // 只能在 setVersion 事务中创建 Object Stores; 
		 if (dbInfo.dbVersion!= db.version) { 
			 var setVReq = db.setVersion(dbInfo.dbVersion); 
			 // onsuccess 方法是唯一创建 Object Stores 的地方
			 setVReq.onerror = dbError; 
			 setVReq.onsuccess = function() { 
				 if(db.objectStoreNames.contains("ShoppingCart")) { 
          db.deleteObjectStore("ShoppingCart"); 
				 } 
				 db.createObjectStore("ShoppingCart",{keyPath: "id"});
				 refreshShoppingCart(); 
			 }; 
		 } 
		 else{ 
			 refreshShoppingCart(); 
		 } 
	 }; 
	 request.onerror = dbError; 
 } 

 function dbError(error){ 
	 console.error(error); 
 }

2. 添加商品数据

图 1. 添加商品界面
添加商品界面

在 Web SQL Database 中仍需使用传统的 SQL INSERT 操作,向表中添加数据。Web SQL Database API 提供的方法可以使用参数形式向表中插入数据。

清单 3. Web SQL Database 添加数据操作
 function insertDataToShoppingCart(data){ 
	 db.transaction(function(tx){ 
		 tx.executeSql("INSERT INTO ShoppingCart " + 
			"(Id, Name,Price,Count,Desc) VALUES (?,?,?,?,?)" , 
			 [data.id, data.name,data.price,data.count,data.desc], 
			 function(tx, result){ 
				 refreshShoppingCart(); 
			 }, 
			 dbError 
		 ); 
	 }); 
 }

在 Indexed Database 中需要使用 ObjectStore 的 put 方法,把 key 和 value 添加到 ObjectStore 中。

清单 4. Indexed Database 添加数据操作
 //data 是个 JavaScript 对象结构是 {id:String,item:Object} 
 //data 中的 item 属性是个对象,包括商品的信息,例如名称,价格等
 function insertOrUpdateDataToShoppingCart(data){ 
	 console.log("insertOrUpdateDataToShoppingCart",data); 
	 var trans = db.transaction(["ShoppingCart"], IDBTransaction.READ_WRITE); 
	 var store = trans.objectStore("ShoppingCart"); 
	 var request = store.put(data); 
	 request.onsuccess = function(e) { 
		 refreshShoppingCart(); 
	 }; 
	 request.onerror = dbError; 
 }

3. 读取商品数据

图 2. 购物车列表界面
购物车列表界面

在 Web SQL Database 可以使用 SQL 的 SELECT 语句查询出所有的记录,然后遍历行数据,获取所有商品信息。

清单 5. Web SQL Database 读取数据操作
 function refreshShoppingCart(){ 
	 dojo.byId("shoppingCartTableData").innerHTML=""; 
	 db.transaction(function(tx){ 
		 tx.executeSql("SELECT * FROM ShoppingCart" ,[], 
			 function(tx, result){ 
				 for(var i=0;i<result.rows.length;i++){  
          var item=result.rows.item(i); 
          var shoppingCart = dojo.byId("shoppingCartTableData"); 
          var tableRow = dojo.create("tr",{},shoppingCart); 
          dojo.create("td",{"innerHTML":item.Name},tableRow); 
          dojo.create("td",{"innerHTML":item.Price},tableRow); 
          dojo.create("td",{"innerHTML":item.Count},tableRow); 
          dojo.create("td",{"innerHTML":item.Desc},tableRow); 
          dojo.create("td",{"innerHTML":item.Price*item.Count},tableRow); 
          var actions = dojo.create("td",{},tableRow); 
          var btnDelete = new dijit.form.Button({ 
						"label":"删除", 
						"onClick":(function(id){ 
		          return function(){deleteDataFromShoppingCart(id)}} 
	          )(item.Id) 
          }); 
          var btnUpdate = new dijit.form.Button({ 
                         "label":"更新", 
                         "onClick":(function(item){return function(){ 
		          showUpdateDataDialog( 
			          {id:item.Id,name:item.Name,price:item.Price, 
			          count:item.Count,desc:item.Desc}); 
	          }})(item) 
          }); 
          actions.appendChild(btnDelete.domNode); 
          actions.appendChild(btnUpdate.domNode); 
				 } 
			 }, 
			 dbError 
		 ); 
	 }); 
 }

在 Indexed Database 中需要根据其提供的查询 API 进行数据的查询。这里使用 IDBKeyRange 这个对象确定需要查询数据的上下限,在调用 ObjectStore 提供的 openCursor 方法,传进 IDBKeyRange 对象作为参数。然后像使用数据库游标一样,在 onsuccess 回调方法中,获取数据对象,每次获取下一行数据时需要调用 result 对象的 continue 方法。

清单 6. Indexed Database 读取数据操作
 function refreshShoppingCart(){ 
	 dojo.byId("shoppingCartTableData").innerHTML=""; 
	 var trans = db.transaction(["ShoppingCart"], IDBTransaction.READ_ONLY); 
	 var store = trans.objectStore("ShoppingCart"); 
	 var keyRange = IDBKeyRange.lowerBound(0);// 查询所有数据
	 var cursorReq = store.openCursor(keyRange); 
	 cursorReq.onsuccess = function(evt) { 
		 var result = evt.target.result; 
		 if(!result)return;// 没有数据返回
		 var item = result.value.item 
		 var shoppingCart = dojo.byId("shoppingCartTableData"); 
		 var tableRow = dojo.create("tr",{},shoppingCart); 
		 dojo.create("td",{"innerHTML":item.name},tableRow); 
		 dojo.create("td",{"innerHTML":item.price},tableRow); 
		 dojo.create("td",{"innerHTML":item.count},tableRow); 
		 dojo.create("td",{"innerHTML":item.desc},tableRow); 
		 dojo.create("td",{"innerHTML":item.price*item.count},tableRow); 
		 var actions = dojo.create("td",{},tableRow); 
		 var btnDelete = new dijit.form.Button({ 
			"label":"删除", 
			"onClick":(function(id){ 
				 return function(){deleteDataFromShoppingCart(id)}} 
			 )(result.value.id) 
		 }); 
		 var btnUpdate = new dijit.form.Button({ 
			"label":"更新", 
			"onClick":(function(item){return function(){ 
		  showUpdateDataDialog({id:result.value.id,name:item.name, 
          price:item.price,count:item.count,desc:item.desc}); 
			 }})(item) 
		 }); 
		 actions.appendChild(btnDelete.domNode); 
		 actions.appendChild(btnUpdate.domNode); 
		 result.continue();// 继续读取下一行操作
	 }; 
	 cursorReq.onerror = dbError; 
 }

3. 更新商品数据

图 3. 更新商品信息界面
更新商品信息界面

在 Web SQL Database 中需要使用传统的 SQL UPDATE 操作更新数据库表中的数据。

清单 7. Web SQL Database 更新数据操作
 function updateDataToShoppingCart(data){ 
	 console.log("updateDataToShoppingCart",data); 
	 db.transaction(function(tx){ 
		 tx.executeSql("UPDATE ShoppingCart SET " + 
			"Name = ?, Price = ? , Count = ?,Desc = ? WHERE Id = ?" , 
			 [data.name,data.price,data.count,data.desc,data.id], 
			 function(tx, result){ 
				 refreshShoppingCart(); 
			 }, 
			 dbError 
		 ); 
	 }); 
 }

在 Indexed Database 操作中,更新数据和添加数据的方法是一样,如果 data 中的 id 在 ObjectStore 中已经存在了,将进行更新操作,否则将添加新数据

清单 8. Indexed Database 更新数据操作
 function insertOrUpdateDataToShoppingCart(data){ 
	 console.log("insertOrUpdateDataToShoppingCart",data); 
	 var trans = db.transaction(["ShoppingCart"], IDBTransaction.READ_WRITE); 
	 var store = trans.objectStore("ShoppingCart"); 
	 var request = store.put(data); 
	 request.onsuccess = function(e) { 
		 refreshShoppingCart(); 
	 }; 
	 request.onerror = dbError; 
 } 3

3. 删除商品数据

在 Web SQL Database 中需要使用传统的 SQL DELETE 操作删除数据库中表记录。

清单 9. Web SQL Database 删除数据操作
 function deleteDataFromShoppingCart(id){ 
	 console.log("deleteDataFromShoppingCart",id); 
	 db.transaction(function(tx){ 
		 tx.executeSql("DELETE FROM ShoppingCart WHERE Id = ?" , 
			 [id], 
			 function(tx, result){ 
				 refreshShoppingCart(); 
			 }, 
			 dbError 
		 ); 
	 }); 
 }

在 Indexed Database 中,需要使用 API 中 ObjectStore 的 delete 方法,传进 key 值作为参数,删除相应的记录。

清单 10. Indexed Database 删除数据操作
 function deleteDataFromShoppingCart(id){ 
	 console.log("deleteDataFromShoppingCart",id); 
	 var trans = db.transaction(["ShoppingCart"], IDBTransaction.READ_WRITE); 
	 var store = trans.objectStore("ShoppingCart"); 
	 var request = store.delete(id); 
	 request.onsuccess = function(e) { 
		 refreshShoppingCart(); 
	 }; 
	 request.onerror = dbError; 
 }

结束语

本文基于购物车示例详细介绍了 Web SQL Database 和 Indexed Database 的 CRUD 操作,从代码简洁程度来看,Indexed Database 的操作更清晰。但 Web SQL Database 的 操作方式对传统开发人员来说更友好。由于在不同的平台上浏览器对两种客户端数据库的支持程度的差异,分别掌握两种客户端数据库的操作方法还是非常有必要的。 随着 HTML5 规范的发展,相信未来在客户端存储数据将会越来越容易。





文章二,HTML5 内置本地数据库之Sqlite

一、关于HTML5和web本地数据库

SQLite 可以很好的支持关系型数据库所具备的一些基本特征,如标准SQL语法、事物、数据表和索引等,且占用资源较少,可在移动设备上轻松使用。 
HTML5中添加了很多功能,将一些以前必须保存在服务器上的数据转向本地保存,提高了Web应用程序性能的同时还减轻了服务器的负担。然而关于Web SQL Database有一个不太好的消息(来自网络):

我们经常在数据库中处理大量结构化数据,Html5引入Web SQL Database概念,它使用 SQL 来操纵客户端数据库的 API,这些 API 是异步的,规范中使用的是SQLlite,悲剧正是产生于此,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),但是我们需要更多的独立实现来完成标准化。

也就是说这是一个废弃的标准了,虽然部分浏览器已经实现

一上来就泼凉水确实不太好 ,但是学习一下总归没有什么坏处的,对吧? 
目前我已知的支持Web SQL Database的浏览器有chrome(估计还有别的,只是我没用到~),然而火狐和IE并不支持。 
W3C目前力推的H5本地数据库是IndexedDB

二、H5 Sqlite数据库三个核心API

opendatabase:使用现有数据库或创建新数据库创建数据库对象

var db = openDatabase('myTel','1.0','test db',1024*100);
//四个参数分别是数据库名 版本 数据库描述 大小
//当该数据库不存在的时候创建并打开数据库,否则直接打开数据库。
//创建的数据库存于本地浏览器的Cache 文件夹。
 
  • 1
  • 2
  • 3
  • 4
  • 1
  • 2
  • 3
  • 4

transaction:事务,可根据情况控制事务提交或回滚

db.transaction(callback)
//用作事务处理,来操作数据库

 
  • 1
  • 2
  • 3
  • 1
  • 2
  • 3

executeSql:用于执行SQL查询

db.transaction(function(tx){
    tx.executeSql('SQL语句',[参数数组],dataHandler,errorHandler)
})
//executeSql的四个参数:
//1、操作数据库的SQL语句
//2、SQL语句中使用的参数的数组
//3、语句操作成功调用的方法
//4、语句操作失败调用的方法
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8

关于dataHandler和errorHandler:

function dataHandler(transaction,results);
// 其中,results的rows属性中保存了查询到的每一条记录,rows.length属性可以获取记录的条数
// 可使用rows[index]或rows[item]来单独取到某条记录
function errorHandler(transaction,errMsg);
 
  • 1
  • 2
  • 3
  • 4
  • 1
  • 2
  • 3
  • 4

三、一个例子

下面使用一个比较完整的例子来演示。

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Sqlite</title>
</head>
<body onload="init()">
    <!-- 创建数据库对象、使用事务进行数据库操作 -->
    姓名:<input type="text" id="name"/>
    电话:<input type="text" id="tel" />
    <input type="button" value="保存" onclick="saveData()" />
    <hr/>
    <input type="button" onclick="showAllData()" value="显示全部">
            <input type="button" onclick="delAllData()" value="清空全部">
    <hr/>
    <table id="datatable" border="1">

    </table>
    <p id="'msg"></p>

</body>
<script type="text/javascript">
    var datatable = null;
    var db = openDatabase('myTel','1.0','test db',1024*100);//数据库名 版本 数据库描述 大小

    function init(){//初始化工作
        datatable = document.getElementById('datatable');
        showAllData();
    }
    function removeAllData(){//移除页面上展示的数据
        for(var i = datatable.childNodes.length-1;i>=0;i--){
            datatable.removeChild(datatable.childNodes[i]);
        }
        var tr = document.createElement('tr');
        var th1 = document.createElement('th');
        var th2 = document.createElement('th');
        th1.innerHTML = '姓名';
        th2.innerHTML = '电话';
        tr.appendChild(th1);
        tr.appendChild(th2);
        datatable.appendChild(tr);

    }
    function showData(row){//显示数据
        var tr = document.createElement('tr');
        var td1 = document.createElement('td');
        td1.innerHTML = row.name;
        var td2 = document.createElement('td');
        td2.innerHTML = row.tel;
        tr.appendChild(td1);
        tr.appendChild(td2);
        datatable.appendChild(tr);
    }
    function showAllData(){//显示所有数据

        db.transaction(function (tx){
            tx.executeSql('create table if not exists TelData(name TEXT,tel TEXT)',[],function(tx,res){

                },function(tx,err){
                    alert(err.message)
                });

            tx.executeSql('select * from TelData',[],function(tx,result){
                removeAllData();
                for(var i = 0 ;i<result.rows.length;i++){
                    showData(result.rows.item(i));
                }
            })
        })
    }
    function saveData(){//保存数据
        var name = document.getElementById('name').value;
        var tel = document.getElementById('tel').value;
        addData(name,tel);
        showAllData();
    }
    function addData(name,tel){//添加数据
        db.transaction(function(tx){
            tx.executeSql('insert into TelData values(?,?)',[name,tel],function(tx,rs){
                alert('yes');
            },
            function (tx,err){
                alert(err.source +'===='+err.message);
            })
        })
    }
    function  delAllData(){//删除所有数据
        db.transaction(function(tx){
            tx.executeSql('delete from TelData',[],function(tx,res){
                alert('删除成功~');
            },function (tx,err){
                alert('删除失败'+err.message);
            })
        })
        showAllData();
    }
</script>
</html>
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73
  • 74
  • 75
  • 76
  • 77
  • 78
  • 79
  • 80
  • 81
  • 82
  • 83
  • 84
  • 85
  • 86
  • 87
  • 88
  • 89
  • 90
  • 91
  • 92
  • 93
  • 94
  • 95
  • 96
  • 97
  • 98
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73
  • 74
  • 75
  • 76
  • 77
  • 78
  • 79
  • 80
  • 81
  • 82
  • 83
  • 84
  • 85
  • 86
  • 87
  • 88
  • 89
  • 90
  • 91
  • 92
  • 93
  • 94
  • 95
  • 96
  • 97
  • 98

执行结果:

添加一条数据:

这里写图片描述

运行结果:

这里写图片描述

再添两条:

这里写图片描述

关闭浏览器后重新打开:

这里写图片描述

全部清空之后

这里写图片描述

文章三,SQLLite本地数据库

本地数据库支持比较少,不够规范,建议少用

本地数据库是H5之后出现的SQLLite数据库,可以通过SQL语言来访问文件型SQL数据库

使用数据库的步骤:

  1. 创建访问数据库
  2. 使用事务处理

创建访问数据库对象 
博客出处 
var db= openDatabase(‘mydb’,’1.0’,’TestDB’,2*1024*1024)

第一个参数:数据库名

第二个参数:版本号

第三个参数:数据库描述

第四个参数:数据库大小

该方法返回创建后的数据库访问对象,如果该数据库不存在,则创建数据库

用executeSql执行查询

transaction.executeSql(sqlquery,[],dataHandler,errorHandler);

第一个参数:查询语句

第二个参数:查询语句中的?

eg: transaction.executeSql(“UPDATE people set age=? which name=?”,[age,name])

第三个参数:执行成功时调用的回调函数

function dataHandler(transaction,result){//回调函数内容}

第四个参数:执行失败时调用的回调函数

function errorHandler(transaction,erromsg){//alert(“执行出错!”)}

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Sqlite</title>
</head>
<body onload="init()">
    <!-- 创建数据库对象、使用事务进行数据库操作 -->
    姓名:<input type="text" id="name"/>
    电话:<input type="text" id="tel" />
    <input type="button" value="保存" onclick="saveData()" />
    <hr/>
    <input type="button" onclick="showAllData()" value="显示全部">
            <input type="button" onclick="delAllData()" value="清空全部">
    <hr/>
    <table id="datatable" border="1">

    </table>
    <p id="'msg"></p>

</body>
<script type="text/javascript">
    var datatable = null;
    var db = openDatabase('myTel','1.0','test db',1024*100);//数据库名 版本 数据库描述 大小

    function init(){//初始化工作
        datatable = document.getElementById('datatable');
        showAllData();
    }
    function removeAllData(){//移除页面上展示的数据
        for(var i = datatable.childNodes.length-1;i>=0;i--){
            datatable.removeChild(datatable.childNodes[i]);
        }
        var tr = document.createElement('tr');
        var th1 = document.createElement('th');
        var th2 = document.createElement('th');
        th1.innerHTML = '姓名';
        th2.innerHTML = '电话';
        tr.appendChild(th1);
        tr.appendChild(th2);
        datatable.appendChild(tr);

    }
    function showData(row){//显示数据
        var tr = document.createElement('tr');
        var td1 = document.createElement('td');
        td1.innerHTML = row.name;
        var td2 = document.createElement('td');
        td2.innerHTML = row.tel;
        tr.appendChild(td1);
        tr.appendChild(td2);
        datatable.appendChild(tr);
    }
    function showAllData(){//显示所有数据

        db.transaction(function (tx){
            tx.executeSql('create table if not exists TelData(name TEXT,tel TEXT)',[],function(tx,res){

                },function(tx,err){
                    alert(err.message)
                });

            tx.executeSql('select * from TelData',[],function(tx,result){
                removeAllData();
                for(var i = 0 ;i<result.rows.length;i++){
                    showData(result.rows.item(i));
                }
            })
        })
    }
    function saveData(){//保存数据
        var name = document.getElementById('name').value;
        var tel = document.getElementById('tel').value;
        addData(name,tel);
        showAllData();
    }
    function addData(name,tel){//添加数据
        db.transaction(function(tx){
            tx.executeSql('insert into TelData values(?,?)',[name,tel],function(tx,rs){
                alert('yes');
            },
            function (tx,err){
                alert(err.source +'===='+err.message);
            })
        })
    }
    function  delAllData(){//删除所有数据
        db.transaction(function(tx){
            tx.executeSql('delete from TelData',[],function(tx,res){
                alert('删除成功~');
            },function (tx,err){
                alert('删除失败'+err.message);
            })
        })
        showAllData();
    }
</script>
</html>

26、探索Web存储与离线应用开发 本文介绍了Web存储API的使用以及离线应用开发的相关知识。涵盖了Web SQL数据库和Indexed Database API的特点及浏览器支持情况,同时讨论了JSON对象存储、跨窗口共享数据等实用技巧。此外,还详细讲解了HTML5离线应用的工作流程、缓存清单文件的编写、更新策略以及兼容性测试等内容,为开发者提供了全面的技术指导。 阅读详情

相关推荐

webview的缓存

缓存模式 LOAD_CACHE_ONLY: 不使用网络,只读取本地缓存数据 LOAD_NO_CACHE: 不使用缓存,只从网络获取数据. LOAD_DEFAULT: (默认)根据cache-control决定是否从网络上取数据。 LOAD_CACHE_ELSE_NETWORK 只要本地有,无论是否过期,或者no-cache,都使用缓存中的数据 Android WebView自带的缓...

海阔天空 3329

保存大量数据用sqllite还是indexdb

**用户体验**:SQLite 通常提供更快的查询性能,但如果应用在 Webview 中运行,使用 IndexDB 可能会提供更好的用户体验,因为它不会阻塞主线程。- **如果你的应用主要运行在 H5 环境或 Webview 中**,并且需要一种轻量级的解决方案来存储大量数据,IndexDB 可能更适合。- **如果应用是编译到原生平台的**(如 iOS 或 Android),并且需要高性能的数据处理,那么 SQLite 可能是更好的选择。- 适用于需要离线存储、复杂查询和事务管理的应用。

qq_34874784的博客 1338

OpenHarmony系统参数权限配置避坑指南:从param get/set失败到SELinux标签实战

本文深入解析OpenHarmony系统参数权限配置的常见问题与解决方案,涵盖DAC和SELinux双重权限控制机制。通过实战案例演示如何配置`param get/set`权限,解决'Permission denied'错误,并提供三方应用访问参数的安全方案,帮助开发者高效完成系统调试与优化。

weixin_27013291的博客 450

前端的存储:websql和indexedDB

关于存储,我们大多都知道存储的老伙计localStorage和sessionStorage、cookie等 今天就继续了解下websql和indexedDB的使用(js的红宝书上有详细介绍) WebSQL:(不再维护,当扩展看看就好) 其弥补前端的关系型存储。底层实现是通过sqlite这个轻量级的数据库。 只有极少数的浏览器支持(chrome等)【其他浏览器不去实现是因为webSQL这...

手写我对你的温柔 2314

基于角谱传播的MATLAB仿真:从相位恢复看自由空间光传播

本文详细介绍了基于角谱传播理论的MATLAB仿真方法,用于模拟自由空间光传播过程。通过傅里叶光学原理,将光场分解为频谱并应用传播相位滤波器,实现了从纯相位物体到可观测衍射图样的仿真。文章结合具体代码,演示了如何利用角谱法进行相位恢复,为计算成像和生物医学检测等领域的研究提供了实用的仿真工具和思路。

weixin_29055699的博客 283

Underactuated Robotics - 欠驱动机器人学(一)- 全驱动与欠驱动系统

根据牛顿的观点,机械系统的动力学是二阶的(其状态由位置向量 q(也称为配置向量)和速度向量以及(可能还有)时间给出。二阶控制动力系统的一般形式是:其中 u 是控制向量。定义 1.1 (欠驱动控制微分方程) 二阶控制微分方程描述如下:在状态和时间 t 中,如果所得到的映射是可射的:对于每一个,都存在一个能产生预期响应的,那么系统就是全驱动的。否则,就是欠驱动(状态在时间 t)。

机器人控制与仿真应用 3377

数据交互系列:indexDB和WebSQL客户端离线存储大量数据

随着浏览器的功能不断增强,越来越多的网站开始考虑,将大量的数据存储在客户端,这样可以减少服务端获取数据,直接从本地获取数据。现有的浏览器数据存储方案cookie 大小不超过4kbLocalStorage 大小在2.5M到10M之间(各家浏览器不同),而且只存储键值对,不提供搜索功能,不能建立自定义的索引。MDN官网是这样解释indexedDB的。

Code_King006的博客 2510

万字长文,YOLOv8 yaml 文件解析 | 一文搞定 YOLOv8 分类任务,检测任务,分割任务,关键点任务

YOLOv8 yaml 文件解析 | 一文搞定 YOLOv8 分类任务,检测任务,分割任务,关键点任务

Coding... 1万+

各个数据库存二进制大文件性能测试

​ 有个项目软件前端将二进制大文件存在了indexDB,每次给后端传文件(需要传到底层C++进行调用)都会导致内存占用飙升,想着使用前后端都能共同操作的数据库来解决这个内存占用的问题,并且希望这个更具尽可能的轻量,可以嵌入到程序中是最好的,通过一个安装包进行安装。

softshow1026的博客 636

openpi 入门教程(一)安装、训练、微调与推理

OpenPI是由物理智能团队发布的机器人开源模型和软件包,包含两种主要模型:基于流的扩散视觉-语言-动作模型(VLA)的π₀模型和基于FAST动作标记器的自回归VLA的π₀-FAST模型。这些模型已在超过10,000小时的机器人数据上进行了预训练,并提供了基础模型检查点,支持开箱即用或根据用户数据集进行微调。OpenPI的实验性质意味着它可能不适用于所有平台,但鼓励研究人员和从业者进行创造性实验。运行这些模型需要至少具备NVIDIA GPU,推荐使用RTX 4090或更高规格的显卡。OpenPI支持在Ubu

2506_90492529的博客 5113

芯片ATE测试PAT(Part Average Testing)学习总结-20250916

文章摘要:零件平均测试(PAT)是半导体制造中基于统计学的质量控制方法,分为静态和动态两种类型。静态PAT通过预先设定的固定限值(每6-8批次更新)筛选异常芯片,计算采用稳健平均值和四分位间距。动态PAT则根据实时数据调整限值,能更精确识别异常而不误判合格芯片。两种方法均采用"均值±6倍标准差"的计算公式,但动态PAT具有更好的适应性和准确性。该方法通过统计分析提高了芯片产品的质量和可靠性。

歌颂苦难的行为是无耻的; 1193

本地存储(LocalStorage、SessionStorage、Web SQL Database、Indexed DB)

https://www.cnblogs.com/SeeYouBug/p/6127001.html https://blog.youkuaiyun.com/inter_peng/article/details/49133081 https://blog.youkuaiyun.com/qiqingjin/article/details/53263261

weixin_34101229的博客 106

一个非常简单的变分量子分类器 (VQC)

​ 在之前的帖子(这里和这里)中,我已经开始谈论 QML,为什么以及如何学习,从现在开始,我将开始分享我的研究和发现,到目前为止,这些都是非常基本的。​

gongdiwudu的专栏 6210

HTML5 Web SQL Database 与 Indexed Database 的 CRUD 操作

http://www.ibm.com/developerworks/cn/web/1210_jiangjj_html5db/   Web SQL Database 和 Indexed Database 都是在客户端存储大量结构化数据的解决方案。Web SQL Database 实现了传统的基于 SQL 语句的数据库操作,而 Indexed Database 实现了 NoSQL ...

蘑蘑茶 474

【系统架构设计师-2025上半年真题】综合知识-参考答案及详解(75题完全回忆版)

【系统架构设计师-2025上半年真题】案例分析-参考答案及部分详解

数据知道的博客 1万+

VC中sqlite的使用

在VC中对sqlite的使用,实现数据库大批数据的快速插入,读取数据库中的数据在ListCtrl中显示

HTML5 Web SQL Database与Indexed Database的CRUD操作

HTML5 Web SQL Database与Indexed Database的CRUD操作 HTML5 简介 HTML标准自1999年12月发布的HTML 4.01后,后继的HTML 5和其它标准被束之高阁,为了推动Web标准化运动的发展,一些公司联合起来,成立了一个叫做Web Hypertext Application Technology Working Gr

不了了之之了之 835

IMSL CNL 7.0.0 (x86-64)Crack

IMSL CNL 7.0.0 (x86-64)Crack intel的算法库破解文件,这是C++版本的破解文件

HTML5 基础(003_Web SQL Database_1)

Web SQL 数据库: Web SQL 数据库 API 并不是 HTML5 规范的一部分,它是一个独立的规范,引入了一组使用 SQL 操作客户端数据库的 APIs。 万维网联盟(W3C)已经不再对 Web SQL 数据库 API 这一规范进行维护,新的替代者为 Indexed Database API(稍后再讨论)。 客户端数据库的出现是为了能够在客户端存储可观数量的结构化数据,并且在这些数据上使

Google2606的博客 748

visio安装包

Microsoft Office Visio 是一款专业的制图软件。利用经过更新的形状、协作工具和数据链接图表,创建专业级图表以简化复杂的信息。

迈瑞BS系列全自动生化分析仪LIS协议接口手册(内含HL7和ASTM)

迈瑞BS系列全自动生化分析仪LIS协议接口手册,内含HL7和ASTM)

Html5本地存储之Web SQL&nbsp…

在HTML5出现之前,对能在HTML画面当中通过JavaScript操作数据库是不可想象的。HTML5标准中包含了Web SQL Database标准,尽管还还处于草案阶段最终肯定会在新版的浏览器中得到广泛的应用,现在已经可以肯定会在各型智能手机中得到应用。 Web SQL Database提供了使用SQL操作关系数据库的功能。Chrome、Safari、Oprea等Web浏览器当中已经支持了此功

793

HTML5 FEATURES STORAGE

HTML5 FEATURES STORAGE When web developers think of storing anything about the user, they immediately think of uploading to the server. HTML5 changes that, as there are now several technologies

Arther90的专栏 992

Web SQL& IndexedDB

Web SQL& IndexedDB https://developer.mozilla.org/en/docs/Web/API/IndexedDB_API https://mdn.github.io/to-do-notifications/ https://www.cnblogs.com/xgqfrms/p/5835942.html web 存储方式汇总 Cookies...

weixin_30877181的博客 181

android h5使用缓存_手把手教你构建 Android WebView 的缓存机制 & 资源预加载方案

下面会详细介绍:1.1.1 渲染速度慢前端H5页面渲染的速度取决于 两个方面:Js 解析效率 Js 本身的解析过程复杂、解析速度不快 & 前端页面涉及较多 JS 代码文件,所以叠加起来会导致 Js 解析效率非常低手机硬件设备的性能 由于Android机型碎片化,这导致手机硬件设备的性能不可控,而大多数的Android手机硬件设备无法达到很好很好的硬件性能总结:上述两个原因 导致 H5页面的...

weixin_30747571的博客 1019
上一篇: 前端HTML5几种存储方式的总结
下一篇: js获取url汇总
function__
博客等级 码龄10年 99粉丝 39原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值