一、什么叫數據庫
DB的全名是database,即數據庫。
二、數據庫的種類
數據庫有兩種類型,分別是關系型數據庫和非關系型數據庫。
- 關系型數據庫:Oracle、DB2、MicrosoftSQLServer、MicrosoftAccess、MySQL等。
- 非關系型數據庫:NoSql、Cloudant、MongoDb、redis、HBase等。
關系型數據庫的優點:
- 能夠復雜查詢:可以用SQL句子便捷的在一個表及多個表之間做復雜的數據查詢。
- 事務支持性優秀:能夠實現對於安全性要求很高的數據訪問。
非關系型數據庫的優點:
- 性能好:NOSQL是基於鍵值對的,可以想象成表中的主鍵和值的對應關系,並且不用通過SQL層的解析,因此性能表現優異。
- 可擴展性好:同樣也是基於鍵值對,數據間耦合度低,因此很容易水平擴展。
- SQL (Structured Query Language) 是一種數據庫語言 。
- 就數據庫類型而言,IndexedDB 不屬於關系型數據庫(不支持 SQL 查詢語句),更接近 NoSQL 數據庫。
IndexedDB 具有以下特點
(1)鍵值對儲存。 IndexedDB 內部采用對象倉庫(object store)存放數據。所有類型的數據都可以直接存入,包括 JavaScript 對象。對象倉庫中,數據以"鍵值對"的形式保存,每一個數據記錄都有對應的主鍵,主鍵是獨一無二的,不能有重復,否則會拋出一個錯誤。
(2)異步。 IndexedDB 操作時不會鎖死瀏覽器,用戶依然可以進行其他操作,這與 LocalStorage 形成對比,后者的操作是同步的。異步設計是為了防止大量數據的讀寫,拖慢網頁的表現。
(3)支持事務。 IndexedDB 支持事務(transaction),這意味着一系列操作步驟之中,只要有一步失敗,整個事務就都取消,數據庫回滾到事務發生之前的狀態,不存在只改寫一部分數據的情況。
(4)同源限制 IndexedDB 受到同源限制,每一個數據庫對應創建它的域名。網頁只能訪問自身域名下的數據庫,而不能訪問跨域的數據庫。
(5)儲存空間大 IndexedDB 的儲存空間比 LocalStorage 大得多,一般來說不少於 250MB,甚至沒有上限。
(6)支持二進制儲存。 IndexedDB 不僅可以儲存字符串,還可以儲存二進制數據(ArrayBuffer 對象和 Blob 對象)。
- 數據庫是一系列相關數據的容器。
- 每個數據庫包含若干個對象倉庫(object store)。它類似於關系型數據庫的表格。
- 對象倉庫保存的是數據記錄。每條記錄類似於關系型數據庫的行,但是只有主鍵和數據體兩部分。
- 數據庫 > 對象倉庫 > 數據記錄
操作流程
-
打開數據庫: indexedDB.open()
var version = 1; var databaseName = "database"; var request = window.indexedDB.open(databaseName, version);//這是一個異步操作,但是會立刻返回一個IDBOpenDBRequest對象。方法返回一個IDBRequest對象。這個對象通過三種事件error、success、upgradeneeded處理打開數據庫的操作結果。 var db; /** * 新建數據庫與打開數據庫是同一個操作。 * 如果要打開的數據庫不存在,則會先新建數據庫: * 1. 新建數據庫時調用 request.onupgradeneeded(因為這時版本從無到有,所以會觸發這個事件) * 2. 把數據庫版本設為 1 * 3. 此時數據庫對象 db = e.target.result; * 新建數據庫后,就可以打開數據庫了,所以繼續調用 request.onsuccess * */ request.onupgradeneeded = function(e) { db = e.target.result; console.log("onupgrageneeded"); // 通常新建數據庫以后,第一件事是新建對象倉庫(即新建表),並設置主鍵 var objectStore = db.createObjectStore("person", { keyPath: "id" //設置主鍵為 id }); } /** * 如果要打開的數據庫存在,則會直接打開該數據庫 * 此時數據庫對象 db = request.result; * */ request.onsuccess = function(e) { db = request.result; console.log("success"); } /** * 數據庫打開錯誤時調用此回調函數 * */ request.onerror = function(e) { console.log("error"); }
-
新建數據庫:
新建數據庫與打開數據庫是同一個操作。如果指定的數據庫不存在,就會新建。
a. 新建對象倉庫(即新建表)。
request.onupgradeneeded = function(e) { db = e.target.result; console.log("onupgrageneeded"); // 通常,新建數據庫以后,第一件事是新建對象倉庫(即新建表),並設置主鍵 var objectStore = db.createObjectStore("person", { keyPath: "id" //設置主鍵為 id }); }
request.onupgradeneeded = function(e) { db = e.target.result; console.log("onupgrageneeded"); // 通常新建數據庫以后,第一件事是新建對象倉庫(即新建表),並設置主鍵 var objectStore; if(!db.objectStoreNames.contains(databaseName)) {//如果這個 對象倉庫/表 不存在,就新建 objectStore = db.createObjectStore("person", { keyPath: "id" //設置主鍵為 id }); } }
var objectStore = db.createObjectStore("person", { autoIncrement: true }); //指定主鍵為一個遞增的整數
d. 新建數據庫后可以新建當前數據庫的索引,使用索引可以更方便的查詢數據。
/** * 新建當前數據庫的索引 * 必須在VersionChange監聽函數里調用 * objectStore.createIndex(indexName, keyPath, objectParameters) * indexName:索引名 * keyPath:主鍵 * objectParameters:配置對象(可選) * unique:如果設為 true,將不允許重復的值 * multiEntry:如果設為 true,對於有多個值的主鍵數組,每個值將在索引里面新建一個條目,否則主鍵數組對應一個條目。 * * */ objectStore.createIndex("name","name",{unique:false});//可以重復 objectStore.createIndex("age","age",{unique:false});//可以重復 objectStore.createIndex("email","email",{unique:true});//不能重復
使用索引查詢代碼如下:
useIndex() { var db = this.db; var objectStore = db.transaction("person","readonly").objectStore("person"); var index = objectStore.index("name"); var request = index.get("張三"); //只返回第一個 // var request = index.getAll("張三");//返回所有的 “張三” request.onsuccess = function(e){ var result = e.target.result; if(result){ console.log("result:",result); console.log("索引查詢成功"); }else{ console.log("索引查詢失敗"); } } },
-
新增數據:
新增數據指的是向對象倉庫寫入數據記錄。這需要通過事務完成。var obj1 = {id:1,name:"張三",age:24,email:"zhangsan@foxmail.com"}; var obj2 = {id:2,name:"李四",age:30,email:"lisi@foxmail.com"}; function addRecord(obj){ var request = db.transaction(["person"],"readwrite") //寫入數據需要新建一個事務。新建時必須指定表格名稱和操作模式(“只讀”或“讀寫”) .objectStore("person") //新建事務以后,通過IDBTransaction.objectStore(name)方法,拿到 IDBObjectStore 對象 .add(obj); //再通過表格對象的add()方法,向表格寫入一條記錄 request.onsuccess = function(e){ console.log("數據寫入成功"); } request.onerror = function(e){ console.log("數據寫入失敗"); } } window.onload = function(){ addRecord(obj1); addRecord(obj2); }
注意:不加window.onload 可能存在異步問題,報undefined錯誤。
執行過代碼后如果對象倉庫仍是空,刷新一下即可:
參考文章:
[1] https://www.shulanxt.com/doc/dbdoc/db-intro
[2] http://www.ruanyifeng.com/blog/2018/07/indexeddb.html
[3] https://wangdoc.com/javascript/bom/indexeddb.html
[4] https://www.bilibili.com/video/BV15J411H7GH
[5] https://developer.mozilla.org/zh-CN/docs/Web/API/IDBObjectStore
[6] https://zhuanlan.zhihu.com/p/399223337