複製鏈接
請複製以下鏈接發送給好友

SQLite

鎖定
SQLite,是一款輕型的數據庫,是遵守ACID關係型數據庫管理系統,它包含在一個相對小的C庫中。它是D.RichardHipp建立的公有領域項目。它的設計目標是嵌入式的,而且已經在很多嵌入式產品中使用了它,它佔用資源非常的低,在嵌入式設備中,可能只需要幾百K的內存就夠了。它能夠支持Windows/Linux/Unix等等主流的操作系統,同時能夠跟很多程序語言相結合,比如 Tcl、C#、PHPJava等,還有ODBC接口,同樣比起Mysql、PostgreSQL這兩款開源的世界著名數據庫管理系統來講,它的處理速度比他們都快。SQLite第一個Alpha版本誕生於2000年5月。 至2021年已經接近有21個年頭,SQLite也迎來了一個版本 SQLite 3已經發布。
中文名
輕型數據庫
外文名
SQLite
發    音
[seklait]
軟件大小
5.1M

SQLite工作原理

不像常見的客户-服務器範例,SQLite引擎不是個程序與之通信的獨立進程,而是連接到程序中成為它的一個主要部分。所以主要的通信協議是在編程語言內的直接API調用。這在消耗總量、延遲時間和整體簡單性上有積極的作用。整個數據庫(定義、表、索引和數據本身)都在宿主主機上存儲在一個單一的文件中。它的簡單的設計是通過在開始一個事務的時候鎖定整個數據文件而完成的。 [1] 

SQLite功能特性

1. ACID事務 [1] 
2. 零配置 – 無需安裝和管理配置
3.儲存在單一磁盤文件中的一個完整的數據庫
4.數據庫文件可以在不同字節順序的機器間自由的共享
5.支持數據庫大小至2TB
6. 足夠小, 大致13萬行C代碼, 4.43M
7. 比一些流行的數據庫在大部分普通數據庫操作要快
8. 簡單, 輕鬆的API
9. 包含TCL綁定, 同時通過Wrapper支持其他語言的綁定
10. 良好註釋的源代碼, 並且有着90%以上的測試覆蓋率
11. 獨立: 沒有額外依賴
12. 源碼完全的開源, 你可以用於任何用途, 包括出售它
13. 支持多種開發語言,C, C++, PHP, Perl, Java, C#,Python, Ruby
SQLite雖然很小巧,但是支持的SQL語句不會遜色於其他開源數據庫,它支持的SQL包括:
ATTACH DATABASE
BEGIN TRANSACTION
comment
COMMIT TRANSACTION
COPY
CREATE TABLE
CREATE TRIGGER
DELETE
DETACH DATABASE
DROP INDEX
DROP TABLE
DROP TRIGGER
DROP VIEW
END TRANSACTION
EXPLAIN
expression
INSERT
ON CONFLICT clause
PRAGMA
REPLACE
ROLLBACK TRANSACTION
SELECT
UPDATE
同時它還支持事務處理功能等等。也有人説它象Microsoft的Access,有時候真的覺得有點像,但是事實上它們區別很大。比如SQLite 支持跨平台,操作簡單,能夠使用很多語言直接創建數據庫,而不象Access一樣需要Office的支持。如果你是個很小型的應用,或者你想做嵌入式開發,沒有合適的數據庫系統,那麼你可以考慮使用SQLite。到2013年10月17日最新版本是 3.8.1 。能在上面獲得源代碼和文檔。同時因為數據庫結構簡單,系統源代碼也不是很多,也適合想研究數據庫系統開發的專業人士. [1] 

SQLite語言綁定

可以從C/C++程序中使用這個庫,還可以獲得對Tcl和一些其他腳本語言的綁定。
CPANDBD::SQLite上有一個Perl的DBI/DBD模塊,它不是到SQLite的接口,而是包括整個SQLite數據庫引擎在其中並不需要任何額外的軟件。
還有一個Python模塊叫做PySQLite。
PHP從PHP5.0開始包含了SQLite,但是自5.1版之後開始成為一個延伸函式庫。SQLite能與PHP4一起工作但不包含在其中。
Rails2.0.3將缺省的數據庫配置改為了SQLite 3。

SQLite數據類型

SQLite的數據類型
首先你會接觸到一個讓你驚訝的名詞: Typelessness(無類型). 對! SQLite是無類型的. 這意味着你可以保存任何類型的數據到你所想要保存的任何表的任何列中, 無論這列聲明的數據類型是什麼(只有在一種情況下不是, 稍後解釋). 對於SQLite來説對字段不指定類型是完全有效的. 如:
Create Table ex1(a, b, c);
誠然SQLite允許忽略數據類型, 但是仍然建議在你的Create Table語句中指定數據類型. 因為數據類型對於你和其他的程序員交流, 或者你準備換掉你的數據庫引擎時能起到一個提示或幫助的作用. SQLite支持常見的數據類型, 如:
CREATE TABLE ex2
a VARCHAR(10),
b NVARCHAR(15),
c TEXT,
d INTEGER,
e FLOAT,
f BOOLEAN,
g CLOB,
h BLOB,
i TIMESTAMP,
j NUMERIC(10,5)
k VARYING CHARACTER (24),
l NATIONAL VARYING CHARACTER(16)
前面提到在某種情況下, SQLite的字段並不是無類型的. 即在字段類型為”Integer Primary Key”時.

SQLite客户端管理

SQLite亦可以作為桌面數據庫使用,以下為第三方SQLite的GUI軟件 [1]  。例如:
SQLiteMan,使用QT開發的一個SQLite客户端,支持多語言、跨平台。
SQLiteSpy 輕量級的SQLite客户端,免費,單文件,界面設計緊湊,很穩定, 功能相對較少,創建表與添加數據均需sql語句,作為數據瀏覽和修改工具極佳。
SQLite Manager, 以火狐瀏覽器的擴展形式提供的SQLite客户端 [1] 
SQLite Database Browser, a graphical client to access SQLite databases [1] 
SqlPro SQL Client, another graphical client to work with SQLite databases。

SQLite使用技巧

用PHP操作sqlite數據庫
a、 如何連接sqlite數據庫?
if ($db = sqlite_open('mysqlitedb', 0666, $sqliteerror)) {
	select * from sqlite_master;echo "數據庫連接成功!";
} else {
	die($sqliteerror);
}
b、 如何列出數據庫中所有的表?
if ($db = sqlite_open('mysqlitedb', 0666, $sqliteerror)) {
	$result = sqlite_array_query($db, 'select * from sqlite_master;');
	foreach ($result as $entry) {
		echo 'talbe name='.$entry['name']."n";
		echo 'sql='.$entry['sql']."n";
		echo "--------------------------------------------------------------------------------";
	}
	sqlite_close($db);
} else {
	die($sqliteerror);
}
c、 對sqlite數據庫的查詢,以及結果集的顯示
if ($db = sqlite_open('mysqlitedb', 0666, $sqliteerror)) {
	$result = sqlite_array_query($db, 'select name, email from user ', SQLITE_ASSOC);
	echo "user表查詢結果:n";echo " n name emailn";
	foreach ($result as $entry) {
		echo ' '.$entry['name']." " $entry['email']."n";
	}
	echo ' ';sqlite_close($db);
} else {
	die($sqliteerror);
}
d、數據庫對象記錄的增加、刪除、修改
sqlite_query($db, "INSERT INTO user VALUES('user".$i."'" ",'user".$i."@ hichina. com')");
sqlite_query($db, "delete from user where user=’user99’");
sqlite_query($db, 'UPDATE user SET email="lilz@ hichina .com" where name="user1"');
用JAVA連接SQLite
先下載SQLite數據庫的JDBC
這裏給出一箇中文站點的URL:(參見擴展閲讀
將下載到的包解壓後得到jar包 sqlitejdbc-v033-nested.jar 放到%JAVA_HOME%\lib 下,
並且將其添加到classpath系統環境變量中,我的classpath系統環境變量為:
.;%JAVA_HOME%\lib;%JAVA_HOME%\lib\dt.jar;%JAVA_HOME%\lib\tools.jar;%JAVA_HOME%\lib\sqlitejdbc-v033-nested.jar
在你的代碼中引用這個驅動:
Class.forName("org.sqlite.JDBC");
Connection conn = DriverManager.getConnection("jdbc:sqlite:filename");//filename為你的SQLite數據名稱
// ... use the database ...
conn.close();
示例程序如下:
import java.sql.*;
import org.sqlite.JDBC;

/** 這是個非常簡單的SQLite的Java程序,
 * 程序中創建數據庫、創建表、然後插入數據,
 * 最後讀出數據顯示出來*/
public class TestSQLite{
  public static void main(String[] args){
    try{
      //連接SQLite的JDBC
      Class.forName("org.sqlite.JDBC");
      //建立一個數據庫名zieckey.db的連接,如果不存在就在當前目錄下創建之
      Connection conn =DriverManager.getConnection("jdbc:sqlite:zieckey.db");
      Statement stat = conn.createStatement();
      stat.executeUpdate("create table tbl1(name varchar(20), salary int);");//創建一個表,兩列
      stat.executeUpdate("insert into tbl1values('ZhangSan',8000);");//插入數據
      stat.executeUpdate("insert into tbl1values('LiSi',7800);");
      stat.executeUpdate("insert into tbl1values('WangWu',5800);");
      stat.executeUpdate("insert into tbl1values('ZhaoLiu',9100);");
      ResultSet rs = stat.executeQuery("select * from tbl1;");//查詢數據
      while(rs.next()){//將查詢到的數據打印出來
        System.out.print("name = "+ rs.getString("name")+" ");//列屬性一
        System.out.println("salary = "+ rs.getString("salary"));//列屬性二
      }
      rs.close();
      conn.close();//結束數據庫的連接
    }catch(Exception e ){
      e.printStackTrace();
    }
  }
}
E:\Coding\java\test>javac TestSQLite.java
# 編譯運行:
E:\Coding\java\test>java TestSQLite
name = ZhangSan salary = 8000
name = LiSi     salary = 7800
name = WangWu   salary = 5800
name = ZhaoLiu  salary = 9100
總結:本文介紹了嵌入式數據庫SQLite在Java中的應用,
通過創建表、插入數據、查詢等操作介紹了在Java中對數據庫的操縱。 [2] 
使用.NET操作SQLLITE
先下載ADO.NET2.0 Provider for SQLite。下載binaries zip版就可以了。下載完後解壓縮,可以在bin目錄下找到System.Data.SQLite.DLL。在vs2008中用Add Reference(添加引用)功能把System.Data.SQLite.DLL加到工程裏就可以了。運行下面代碼 [3]  試試:
string datasource = "e:/tmp/test.db";
System.Data.SQLite.SQLiteConnection.CreateFile(datasource);
//連接數據庫
System.Data.SQLite.SQLiteConnection conn = new System.Data.SQLite.SQLiteConnection();
System.Data.SQLite.SQLiteConnectionStringBuilder connstr = new System.Data.SQLite.SQLiteConnectionStringBuilder();
connstr.DataSource = datasource;connstr.Password = "admin";//設置密碼,SQLite ADO.NET實現了數據庫密碼保護
conn.ConnectionString = connstr.ToString();conn.Open();
//創建表
System.Data.SQLite.SQLiteCommand cmd = new System.Data.SQLite.SQLiteCommand();
string sql = "CREATE TABLE test(username varchar(20),password varchar(20))";
cmd.CommandText = sql;
cmd.Connection = conn;cmd.ExecuteNonQuery();
//插入數據
sql = "INSERT INTO test VALUES('a','b')";
cmd.CommandText = sql;cmd.ExecuteNonQuery();
//取出數據
sql = "SELECT * FROM test";
cmd.CommandText = sql;
System.Data.SQLite.SQLiteDataReader reader = cmd.ExecuteReader();
StringBuilder sb = new StringBuilder();
while (reader.Read()){
  sb.Append("username:").Append(reader.GetString(0)).Append("\n").Append("password:").Append(reader.GetString(1));
}
MessageBox.Show(sb.ToString());
使用linux下的C操作SQLLITE
由於linux下側重使用命令,沒有win的操作容易上手,所以在測試C操作SQLITE時會比較容易出現錯誤,給大家做一個簡單的程序進行測試,演示怎麼應用。
#include <stdio.h> 
#include "sqlite3.h"
int main( void ){
  sqlite3 *db = NULL;
  char *zErrMsg = 0;
  int rc;
  //打開指定的數據庫文件,如果不存在將創建一個同名的數據庫文件
  rc = sqlite3_open("zieckey.db", &db);
  if( rc ){
    fprintf(stderr, "Can't open database: %s\n", sqlite3_errmsg(db));
    sqlite3_close(db);
    exit(1);
  }else 
    printf("You have opened a sqlite3 database"
           " named zieckey.db successfully!\n"
           "Congratulations! Have fun ! ^-^ \n");
  sqlite3_close(db); //關閉數據庫
  return 0;
}
退出,保存。(代碼輸入完成後,按下 Esc 鍵,然後輸入: :wq ,回車就好拉)
好拉,編譯:
[root@localhost temp]# gcc opendbsqlite.c -o db.out
或者遇到這樣的問題:
[root@localhost temp]# gcc opendbsqlite.c -o db.out
opendbsqlite.c:11:21: sqlite3.h: 沒有那個文件或目錄
opendbsqlite.c: In function `main':
opendbsqlite.c:19: `sqlite3' undeclared (first use in this function)
opendbsqlite.c:19: (Each undeclared identifier is reported only once
opendbsqlite.c:19: for each function it appears in.)
opendbsqlite.c:19: `db' undeclared (first use in this function)
這是由於沒有找到頭文件的原因。
也許會碰到類似這樣的問題:
[root@localhost temp]# gcc opendbsqlite.c -o db.out
/tmp/ccTkItnN.o(.text+0x2b): In function `main':
: undefined reference to `sqlite3_open'
/tmp/ccTkItnN.o(.text+0x45): In function `main':
: undefined reference to `sqlite3_errmsg'
/tmp/ccTkItnN.o(.text+0x67): In function `main':
: undefined reference to `sqlite3_close'
/tmp/ccTkItnN.o(.text+0x8f): In function `main':
: undefined reference to `sqlite3_close'
collect2: ld returned 1 exit status
這是個沒有找到庫文件的問題。
[root@localhost temp]# gcc opendbsqlite.c -o db.out -lsqlite3 -L/usr/local/sqlite3/lib -I/usr/local/sqlite3/include
這樣編譯應該就可以了
如果還是有錯誤的話請搜索:(一)Sqlite數據庫連接。有更詳細的説明解釋

SQLite常用函數

SQLite 有許多內置函數用於處理字符串數字數據。下面列出了一些有用的 SQLite 內置函數,且所有函數都是大小寫不敏感,這意味着您可以使用這些函數的小寫形式或大寫形式或混合形式。欲瞭解更多詳情,請查看 SQLite 的官方文檔:
序號 函數 & 描述
1 SQLite COUNT 函數 SQLite COUNT 聚集函數是用來計算一個數據庫表中的行數。
2 SQLite MAX 函數 SQLite MAX 聚合函數允許我們選擇某列的最大值
3 SQLite MIN 函數 SQLite MIN 聚合函數允許我們選擇某列的最小值
4 SQLite AVG 函數 SQLite AVG 聚合函數計算某列的平均值
5 SQLite SUM 函數 SQLite SUM 聚合函數允許為一個數值列計算總和。
6 SQLite RANDOM 函數 SQLite RANDOM 函數返回一個介於 -9223372036854775808 和 +9223372036854775807 之間的偽隨機整數。
7 SQLite ABS 函數 SQLite ABS 函數返回數值參數的絕對值
8 SQLite UPPER 函數 SQLite UPPER 函數把字符串轉換為大寫字母
9 SQLite LOWER 函數 SQLite LOWER 函數把字符串轉換為小寫字母
10 SQLite LENGTH 函數 SQLite LENGTH 函數返回字符串的長度。
11 SQLite sqlite_version 函數 SQLite sqlite_version 函數返回 SQLite 庫的版本。

SQLite歷史版本

從某種程度上説,SQLite最初的構思是在一條軍艦上進行的。當時在通用動力工作的SQLite的作者 [1]  D. Richard Hipp正在為美國海軍編制一種使用在導彈驅逐艦上的程序。那個程序最初運行在Hewlett-Packard UNIX(HPUX)上,後台使用Informix數據庫。對那個具體應用而言,Informix有點兒太強大了。一個有經驗的數據庫管理員(DBA)安裝或升級Informix可能需要一整天,如果是沒經驗的程序員,這個工作可能永遠也做不完。真正需要的只是一個自我包含的數據庫,它易使用並能由程序控制傳導,另外,不管其他軟件是否安裝,它都可以運行。
2000年1月,Hipp開始和一個同事討論關於創建一個簡單的嵌入式SQL數據庫的想法,這個數據庫將使用GNU DBM哈希庫(gdbm)做後台,同時這個數據庫將不需要安裝和管理支持。後來,一有空閒時間,Hipp就開始實施這項工作,2000年8月,SQLite 1.0版發佈了。
按照原定計劃,SQLite 1.0用gdbm作為存儲管理器。然而,Hipp不久就用自己實現的能支持事務和記錄按主鍵存儲的B-tree替換了gdbm。隨着第一次重要升級的進行,SQLite有了穩定的發展,功能和用户也在增長。2001年中期,很多項目--開源的或商業的--都開始使用SQLite。在隨後的幾年中,開源社區的其他成員開始為他們喜歡的腳本語言和程序庫編寫SQLite擴展。一個接着一個,既Perl、Python、RubyJava和其他主流的程序設計語言的擴展之後,新的擴展如SQLite的ODBC接口出現並證明了SQLite的廣泛應用和實用功能。
2004年,SQLite從版本2升級到版本3,這是一次重大升級。
以下是之後的版本更新歷史,可以在官網查詢到。
2004-06-09 - Version 2.8.14 [1] 
2004-06-18 - Version 3.0.0
2007-09-04 - Version 3.5.0
2008-07-16 - Version 3.6.0
2008-11-19 - Version 3.6.6
2009-11-04 - Version 3.6.20
2010-03-09 - Version 3.6.23
2010-07-22 - Version 3.7.0
2010-08-24 - Version 3.7.2
2011-02-01 - Version 3.7.5
2012-06-11 - Release 3.7.13
2012-09-03 - Release 3.7.14
2012-12-12 - Release 3.7.15
2013-03-18 - Release 3.7.16
2013-05-20 - Release 3.7.17
2013-08-26 - Release 3.8.0
2013-10-17 - Release 3.8.1
2013-12-06 - Release 3.8.2
2014-02-03 - Release 3.8.3
2014-03-10 - Release 3.8.4
2014-06-04 - release 3.8.5
2014-08-15 - Release 3.8.6
2014-10-08 - Release 3.8.7 [1] 
2015-01-16 - Release 3.8.8 [1] 

SQLite注意事項

在確定是否在應用程序中使用 SQLite 之前,應該考慮以下幾種情況:
  • 有沒有可用於 SQLite 的網絡服務器。從應用程序運行位於其他計算機上的 SQLite 的惟一方法是從網絡共享運行。這樣會導致一些問題,像 UNIX® 和 Windows® 網絡共享都存在文件鎖定問題。還有由於與訪問網絡共享相關的延遲而帶來的性能下降問題。
  • SQLite 只提供數據庫級的鎖定。雖然有一些增加併發的技巧,但是,如果應用程序需要的是表級別或行級別的鎖定,那麼 DBMS 能夠更好地滿足您的需求。
  • 正如前面提到的,SQLite 可以支持每天大約 100,00 次點擊率的 Web 站點 —— 並且,在某些情況下,可以處理 10 倍於此的通信量。對於具有高通信量或需要支持龐大瀏覽人數的 Web 站點來説,應該考慮使用 DBMS。
  • SQLite 沒有用户帳户概念,而是根據文件系統確定所有數據庫的權限。這會使強制執行存儲配額髮生困難,強制執行用户許可變得不可能。
  • SQLite 支持多數(但不是全部)的 SQL92 標準。不受支持的一些功能包括完全觸發器支持和可寫視圖。
如果您感到其中的任何限制會影響您的應用程序,那麼您應該考慮使用完善的 DBMS。如果您可以解除這些限制問題,並且對快速靈活的嵌入式開源數據庫引擎很感興趣,則應重點考慮使用 SQLite。
一些能夠真正表現 SQLite 優越性能的領域是 Web 站點,可以使用 SQLite 管理應用程序數據、快速應用程序原型製造和培訓工具。
由於資源佔用少、性能良好和零管理成本嵌入式數據庫有了它的用武之地,它將為那些以前無法提供用作持久數據的後端的數據庫的應用程序提供了高效的性能。如今沒有必要使用文本文件來實現持久存儲。SQLite 之類的嵌入式數據庫的易於使用性可以加快應用程序的開發,並使得小型應用程序能夠完全支持複雜的 SQL。這一點對於對於小型設備空間的應用程序來説尤其重要。
嵌入式數據庫對於加快應用程序開發也很重要,尤其是在用於數據庫抽象層(例如PEAR::DB或ezSQL)時。最後,SQLite 正在積極開發中,未來一定會有新的功能,會對開源社區更有用。

SQLite刪除數據恢復方法

1、WAL恢復法
WAL關係型數據庫中用於實現事務性和持久性的一系列技術。數據文件(存儲着表和索引)的修改必須在這些動作被WAL記錄之後才被寫入,即在描述這些改變的日誌記錄被刷到持久存儲以後,數據庫在執行命令之前先將它記下來。比如,人們平時會寫備忘錄,記錄自己要做的事,WAL就是那個備忘錄。SQLite3可以通過命令“PRAGMA journal_mode=WAL”打開WAL模式。
2、Type字段估算法
SQLite中的數據存儲在B+tree葉子頁的單元Data(1~N)區中,其單元結構如圖所示,其中Payload-size表示Payload的大小;Row ID表示當前單元序號;而Header-size表示包括其本身在內的記錄頭的大小。在B+tree數據結構中,描述單元相關信息的單元頭和記錄Type字段總數的記錄頭都以可變長整數形式裏。
然而,SQLite中所存儲的整數在分析被刪除數據的時候,在可變長度區域中可能會存在模糊定位的問題,這無疑會給數據恢復造成困難。因此,為了恢復被刪除的數據的深度,必須確定每個可變長度區域的確切長度。
SQLite 刪除數據後(或WAL模式下檢查點觸發後),SQLite會初始化對應單元的前4字節。其中,前2字節表示下一自由塊的偏移量,後2字節則表示當前自由塊的大小。由於刪除操作僅改變單元前4字節,且Type1的類型被設為NULL,只佔1個字節,因此以可變長整數形式存儲的Payload Size、Row ID以及 Header-size三個區域,無論每個區域佔據多少字節,真正存儲數據的Type(2~N)和Data區域均未改變。這樣,既節省空間,又保持了數據的一致性,同時還為恢復數據帶來便利。為了恢復數據庫表中存儲的具體數據,必須確認數據記錄區,也就是Data區域中每種類型的數據所佔的字節數。而想要確認這一點,就必須先確定單元內容區,也就是Payload區域中每個Type字段的長度值。由於數據刪除僅改變單元前4字節,無法準確得知各字段的大小。為了解決這一問題,根據刪除後Type(2~N)與Data區域均未改變,由於Payload Size、Row ID以及 Headersize三個區域存在結束標誌,並且每款安卓手機各表字段個數固定,因此可以通過探測每個Type字段範圍並計算其大小,確定預提取的數據在表中相應的位置,以及確定每個字段對應的Data區域大小,然後準確讀取每個Data區域所存儲的數據,通過一定的編碼轉譯,來實現數據的恢復。 [4] 
B+tree葉子頁單元結構圖 B+tree葉子頁單元結構圖
參考資料