SQLite資料庫相較於我們常用的Mysql,Oracle而言,實在是輕量得不行(最低只占幾百K的記憶體)。平時開發或生產環境中使用各種類型的資料庫,可能都需要先安裝資料庫服務(server),然後才能通過代碼、命令行或者客戶端工具來操作資料庫,但是SQLite卻有點別具一格,它是一個文件型的關係數據 ...
SQLite資料庫相較於我們常用的Mysql,Oracle而言,實在是輕量得不行(最低只占幾百K的記憶體)。平時開發或生產環境中使用各種類型的資料庫,可能都需要先安裝資料庫服務(server),然後才能通過代碼、命令行或者客戶端工具來操作資料庫,但是SQLite卻有點別具一格,它是一個文件型的關係資料庫,完全不用你安裝,也不需要任何的配置或依賴,去官網下載編譯好的二進位文件解壓就可以使用——第一次使用時,同事直接拷給我一個文件,說這就是SQLite了,我擦嘞還驚了一下,竟然直接對著文件就能執行CRUD命令,這完全刷新了我對資料庫的認知。而它的官網/When to use SQLite也說得特別明確:SQLite is not directly comparable to client/server SQL database engines such as MySQL, Oracle, or SQL Server since SQLite is trying to solve a different problem。是的,它的出現並不是為了和 Mysql,Oracle等資料庫競爭,而是為瞭解決不同的問題;那麼哪些場景適合使用SQLite,哪些場景又適合client/server型資料庫呢?博主本來也想問度娘的,但是發現官網中就有最最合適的解釋:Client/server SQL database engines strive to implement a shared repository of enterprise data; SQLite strives to provide local data storage for individual applications and devices。意譯過來就是說,client/server型的資料庫適合於共用數據的存儲—— 一個server端存儲數據,N個客戶端都可以對數據進行CRUD的操作;而SQLite就完全是一種本地化的文件存儲,加之其非常的輕量,特別適合個人應用和設備,所以,你會發現SQLite在嵌入式設備開發比如移動開發中應用得非常廣泛。博主雖然不是做嵌入式開發的,但是用了一下SQLite發現特別小巧好用,建議大家如果應用程式是併發量不是特別高本地應用,完全可以嘗試使用SQLite這種輕量的資料庫來代替,也省去了安裝繁重的資料庫服務對系統資源的占用。好了,現在正式切入正題,跟著布衣博主一起來嘗試使用SQLite的一些簡單招式——
庫文件下載
要使用SQLite資料庫,如果沒有好同事拷貝給你,就自己去官網下吧。點擊官網下載頁就可以下載最新的SQLite版本(SQLite3),頁面也給出了針對不同平臺的下載版本——
對於Windows 64位操作系統,網上的一些教程都是說要把圖中的 1 、2 一起下載解壓在同一個文件,但是博主不太喜歡盲從,喜歡琢磨原因,一番嘗試後發現,其實只需要下載工具壓縮包 2 就可以進行正常的資料庫操作了,而對於 1 中動態鏈接庫文件的作用,博主也始終沒搞明白,在此還望常用Sqlite的高人能指點一二,博主感激不盡!!!
資料庫連接
① 命令行
上圖中 1 下載的壓縮包解壓後會有三個文件可執行文件 sqldiff.exe、sqlite3.exe和sqlite3_analyzer.exe,開啟cmd切換到解壓目錄,就可以直接通過sqlite3執行SQL命令來操作資料庫。這裡要註意,如果直接雙擊sqlite3打開命令行執行後續命令往往是沒有效果的,博主一番嘗試也無解;有效的方式是切換到該目錄後以 sqlite3 + 資料庫名 的方式開始令行,如果資料庫存在就會直接使用,不存在就會創建一個新的資料庫:
需要說明的是,博主嘗試後發現創建的資料庫名可以是任意的名字,並不一定是.db 結尾,只不過出於規範化的考量,最好還是加上尾碼,這樣一看便知是資料庫文件。SQLite的命令都是點命令,也就是說都是用 . 開頭,並且不以 ; 結尾,使用過程中多熟悉一下就習慣了。這裡博主也只是簡單演示,具體命令行可以 .help 查看或者通過百度、官網渠道查詢,博主不贅述。
② 可視化工具
百度一下,你會發現SQLite有一些專門針對性的可視化連接工具,應該都比較好用,博主沒有去嘗試過,不過使用通用版的Navicat也可以連接SQLite,本著工具歸一的原則,也就沒有必要單獨去下載其他連接工具了。建立資料庫連接也很簡單,不同於其他資料庫需要IP、埠以及用戶名、密碼,SQLite只需要找到我們的創建的資料庫文件掛載,就相當於連接到相應的資料庫了;而新建也很簡單,在建庫目錄下定義好庫文件名字就就可以了,下圖中1 、2 分別顯示瞭如何連接現有的庫文件和創建新的資料庫——
看似簡單,本來無需多言的,但是愛折騰的布衣博主卻有個匪夷所思的發現:使用 Navicat Premium 本進行SQLite的連庫和創建新庫的過程中,根本不需要依賴自己下載解壓的那兩個壓縮包——新建連接的時候我甚至可以掛載一個txt文件併成功建立起連接,而且能進行正常的資料庫SQL操作;創建庫的時候我也可以在任意位置創建任意名字、尾碼名的資料庫,同樣能正常SQL操作。這樣就有點意思了,也就是說電腦上的一切非目錄文件只要你心情好都可以建立連接當成資料庫來使用,太膩(bian)害(tai)了吧?博主換了不同的電腦,包括使用Linux系統,嘗試過後都是如此,唯一合理的解釋就是 Navicat Premium 這廝本身就內置了SQLite資料庫引擎,所以才能直接連接以及創建資料庫。(其實不管是Windows系統還是Linux系統你都可以在系統用戶目錄發現Navicat的連接對象文件)
SQLite 的存儲類型
學習一個新的資料庫,大體從幾個方面來瞭解它——存儲結構、操作語言以及支持存儲的數據類型。既然SQLite是一種關係型資料庫,那麼就支持通用的SQL語言,所以你大可將你深厚的SQL功力運用到SQLite身上愉快的進行你的CRUD操作(當然,一些內置函數和SQL語法還是有所不同)。SQLite比較特殊的其實在於它粗放式的數據存儲類型,而且並不強制的進行類型約束,這點和其他關係型資料庫有很大的不同。如此的結果就是,雖然創建表的時候你指定了某一列應該用什麼數據類型,但實際上你是可以胡來的,比如向整型列中插入文本數據,向字元型中插入日期等等(有個特殊情況就是建表時主鍵設置若為INTEGER PRIMARY KEY【原文:except an INTEGER PRIMARY KEY column】就只能插入整數,插入其他數據類型會報錯)。至於原因,SQLite官網數據類型頁面中Datatypes In SQLite段講得很清楚,博主轉述過來就是說:傳統的關係型資料庫採用的是靜態數據類型系統,一個欄位值的數據類型由存儲其值的列容器決定,而SQLite採用更通用的動態數據類型系統,一個欄位的數據類型只與其值本身有關,而與存儲它的容器無關。
按照官網描述,SQLite支持的數據類型分為以下 5 個存儲類型:
- NULL 空值
- INTEGER 帶符號整型,根據其大小存儲在1, 2, 3, 4, 6,或 8 位元組中
- REAL 浮點型,存儲為一個 8 位元組的IEEE 浮點數
- TEXT 文本類型 (UTF-8, UTF-16BE 或 UTF-16LE編碼格式)
- BLOB 全型(布衣博主自己給的稱謂),存什麼就是什麼
別看只有基本的 5 種存儲類型支持,但由於SQLite採用的是動態數據類型系統,而且存儲類較之普通的數據類型是更加籠統的包含關係,因此能完全相容其它靜態數據類型系統的關係型資料庫。但是這種太自由化的存儲還是有些問題的,比如一個數據列我同時存了一個 400 整型值和 '500' 的文本類型值,這兩個值數據類型不一樣,我這麼比較?所以,根據SQLite官網的說法,為了最大限度與其他關係型資料庫相容,SQLite對數據類型進行了很精巧的設計,就是讓數據列具有類型親和性的特性(其實博主更喜歡某些人翻譯的 類型近似 這種叫法)。當我們創建表做欄位類型聲明的時候,實際上只是表明瞭該列具有的近似類型,在正式插入數據的時候,SQLite引擎才會基於該列的近似類型優先推薦使用 5 種存儲類型中的哪一種來存儲你的數據——註意是推薦,並不強制,也就是說只要你想要亂搞,SQLite也並不會限制你,SQLite是列自由的。所以,建表時欄位類型聲明的限制在SQLite中是被弱化了的。在最新的SQLite版本中,資料庫的每一列都被定義為以下 5 種近似類型的一種,其定義和規則官網/Determination Of Column Affinity段中有做出解釋:
- INTEGER 整型,如果聲明的欄位類型包含字元串“INT”(註意,SQLite大多數情況都不區分大小寫,下同),那麼該欄位類型被分配為INTEGER 近似類型;
- TEXT 文本,如果為欄位聲明的類型中包含了'CHAR'、'CLOB'或'TEXT',該欄位被分配為TEXT親和性。比如'VARCHAR'包含了'CHAR',所以被分配為TEXT 近似類型;
- BLOB 無類型,如果為欄位聲明的類型中包含了'BLOB',或者沒有為該欄位聲明類型,該欄位被分配為BLOB 近似類型;
- REAL 浮點型,如果為欄位聲明的類型中包含了'REAL'、'FLOA'或'DOUB',則該欄位被分配為REAL 近似類型;
- NUMERIC 數值型,除以上情況外的類型,則被分配為NUMERIC 近似類型。
官網上/Affinity Name Examples段落中有一份表格羅列了傳統數據類型作為子集與上述 5 種近似類型如何對應的關係。基於上述近似類型的列敘,可以看出SQLite是從聲明類型的字元串中去匹配列的近似類型來決定數據的存儲類的,因此SQLite很有意思的是創建表時類型聲明可以很隨意,比如我可以聲明一個不存在類型的字元串”chenbenbuyi”,但SQLite會根據規則自動識別為NUMERIC的近似類型,並據此近似類型存儲我的數據——
可能有些人對於上面的數據存儲類還是有些疑惑——根據列的近似類型是如何推斷數據存入後的最終類型呢?按博主的理解,SQLite在基於類型近似做數據存儲轉換的時候是有個推薦優先順序的。比如上面的聲明中,並不存在name聲明的數據類型,所以資料庫會自動匹配為NUMERIC的近似類型。當文本數據('23')被插入到該列時,如果轉換操作不會導致數據信息丟失以及完全可逆,那麼SQLite就會將該文本數據優先轉換為INTEGER或REAL類型的數據(NULL或BLOB類型數據不做轉換),轉換不成功才會按照文本數據存儲——這裡能轉換INTEGER成功;如果存儲列的近似類型為TEXT,那麼自然數據存儲的優先存儲類是TEXT,所以哪怕你存儲的是整型數字,結果存的依然是TEXT。這就是類型近似在數據存儲中的應用。
代碼連接資料庫
代碼連接比較基礎簡單,博主簡單操作一盤,權當複習,雖然實際項目中很少用得這麼基礎。基本上呢,代碼操作資料庫的步驟可以概括為:載入驅動、獲取連接、創建預編譯對象、執行SQL、釋放資源,順口溜一句就是“賈璉欲執釋”。按照這個步驟,首先是要下載SQLite的驅動程式包,將包添加到IDE中並Build Path,然後愉快的擼碼操作——
1 import java.sql.*; 2 3 public class SQLiteTest { 4 public static void main(String[] args) { 5 String driver = "org.sqlite.JDBC"; 6 String url = "jdbc:sqlite:E:\\test.db"; 7 String sql = "select * from chenbenbuyi"; 8 Connection conn = null; 9 Statement stmt = null; 10 ResultSet rs = null; 11 try { 12 //載入驅動 13 Class.forName(driver); 14 //獲取連接 15 conn = DriverManager.getConnection(url); //sqlite不需要密碼 16 //創建預編譯對象 17 stmt = conn.createStatement(); 18 //執行sql 19 rs = stmt.executeQuery(sql); 20 while (rs.next()) { 21 String s = rs.getString("x") +":"+rs.getString("y")+":"+rs.getString("z"); 22 System.out.println(s); 23 } 24 } catch (Exception e) { 25 e.printStackTrace(); 26 } finally { 27 //釋放資源:一定要在finally中確保資源被釋放 28 if (null != rs) { 29 try { 30 rs.close(); 31 } catch (SQLException e) { 32 e.printStackTrace(); 33 } 34 } 35 if (null != stmt) { 36 try { 37 stmt.close(); 38 } catch (SQLException e) { 39 e.printStackTrace(); 40 } 41 } 42 if (null != conn) { 43 try { 44 conn.close(); 45 } catch (SQLException e) { 46 e.printStackTrace(); 47 } 48 } 49 } 50 51 } 52 }
其它註意項
①Sqlite沒有單獨的布爾存儲類型,它使用INTEGER作為存儲類型,0為false,1為true;
②Sqlite沒有單獨的日期和時間存儲類,內置的sqlite日期和時間函數能夠將日期和時間以TEXT,REAL或INTEGER形式存放;
③基於輕量的設計取捨,SQLite的鎖粗粒比較粗,當一個寫連接要寫資料庫,所有其它的連接被鎖住,直到寫連接結束了它的事務,所以多個進程可以同時對SQLIte進行SELECT操作,但在任一時刻,只能有一個進程對資料庫進行更改。SQLite因為不適合於高併發的場景。
尾聲
好了,作為入門,不可能對SQLite講述得太全面,但帶你入門完全夠了,所以本博暫時先止於此。鑒於布衣博主的博客被copy盜取太多,百度一搜甚是氣憤,在此鄭重申明:轉載請獲得博主允許並註明出處以及給出原文鏈接,否則。。。中國這版權行情博主一屌絲也不能把你怎樣,但你的良心就真的不會痛耶?。
結尾涕泣,不知所云。