這是SQLite系列文章第一篇。
SQLite 是遵守 ACID 的關係數據庫管理系統(Relational database management system,簡稱RDBMS),包含在 C 庫中。與其他數據庫相比,SQLite 不是客戶端、服務端數據庫引擎,而是將其嵌入到客戶端中。
這裏將分爲兩篇文章介紹「SQLite的使用」,這一篇包含以下內容:
- 術語
- 數據庫
- 數據庫管理系統
- 關係數據庫管理系統
- SQL
- SQLite 簡介
- 安裝 SQLite
- 數據類型
- 創建數據庫
- 表
- 創建表
- 刪除表
- 插入 INSERT
- 查詢 SELECT
- 運算符
- 算數運算符
- 邏輯運算符
- 比較運算符
- WHERE
- 更新 UPDATE
- 刪除 DELETE
1. 術語
在學習 SQLite 之前,先了解幾個與此相關的術語。
1.1 數據庫
數據庫(database)是有組織的數據集合,通常在計算機系統中以電子的形式存儲、查詢。
1.2 數據庫管理系統
數據庫管理系統(database management system,簡稱DBMS)是與數據庫交互的軟件。數據庫、DBMS和關聯的應用程序總和稱爲數據庫系統。通常,數據庫還用於寬泛的指代任何DBMS、數據庫系統,或與數據庫關聯的應用程序。
1.3 關係數據庫管理系統
每個DBMS都有一個基礎模型,該模型決定數據庫的結構和恢復數據的方式。關係數據庫管理系統是創建在關係模型基礎上的數據庫,藉助集合代數等數學概念和方法來處理數據庫中的數據。
關係模型由關係數據結構、關係操作集合、關係完整性約束三部分組成。
RDBMS 以表的形式存儲數據,DBMS 以文件的形式存儲數據。
DBMS 也可能使用表,但表之間沒有關係。其數據通常以分層形式或導航形式存儲。這意味着單個數據單元將具有一個父節點,零個、一個或多個子節點。
在 RDBMS 中,表具有稱爲主鍵(primary key)的標識符,數據以 table 的形式存儲,這些數值之間的關係也將以 table 的形式存儲。數值可以由系統更新,數據在物理和邏輯上是相互獨立的。
常見 RDBMS 有 MySql、PostgreSQL、SQL Server Express、SQLite等。
1.4 SQL
SQL 全稱是 structured query language,指結構化查詢語言。也就是 SQL 是用於訪問和處理數據庫的標準化的計算機語言。
雖然 SQL 是一門 ANSI 標準的計算機語言,但仍然存在着多種不同版本的 SQL 語言。爲了與 ANSI 標準相兼容,它們必須以相似的方式共同支持一些主要的命令。例如,SELECT、UPDATE、DELETE、INSERT、WHERE等。
2. SQLite 簡介
SQLite 是遵守 ACID 的關係數據庫管理系統,它包含在 C 庫中,實現了大多數 SQL 標準,通常遵循 PostgreSQL 語法。與其他數據庫系統不同,SQLite 不是客戶端/服務端數據庫引擎,而是被集成到客戶端中。
另外,SQLite 具有以下特點:
- 無需單獨的服務器進程,或操作的系統(無服務器的)。
- 無需配置,也就是無需安裝、管理。
- 一個完整的 SQLite 數據庫是存儲在一個單一的跨平臺的磁盤文件。
- 文件小。完全配置時小於400kb,省略可選功能時小於250kb。
- 自給自足,無需任何外部依賴。
- 完全兼容ACID,允許從多個進程、線程安全訪問。
- 支持SQL92 標準的大多數查詢語言。
- 可在 UNIX(Linux、macOS、iOS、Android)和 Windows 中運行。
- 許可協議爲公有領域(public domain)。
與其它 RDBMS 相比,SQLite 具有以下缺點:
- 沒有用戶管理和安全功能。
- 無法輕鬆擴展。
- 當數據量變大時,佔用內存隨之增多,且不易優化。
- 無法自定義。
SQLite 是嵌入式數據庫軟件的首選,是部署最廣泛的數據庫引擎之一,被主流瀏覽器、操作系統、移動設備所使用。
ACID 是指 DBMS 在寫入、更新資料過程中,爲保證事務(transaction)是正確可靠的,所必須具備的四個特性:
- 原子性 atomicity:一個事務中的所有操作,或者全部完成,或者全部不完成,不會結束在中間某個環節。事務在執行過程中發生錯誤,會被回滾(rollback)到事務開始前的狀態,就像這個事務從來沒有執行過一樣。即,事務不可分割、不可約簡。
- 一致性 consistency:在事務開始之前和結束之後,數據庫的完整性沒有被破壞。即寫入的資料完全符合預設約束、觸發器、級聯回滾等。
- 隔離性 isolation:數據庫允許多個併發事務同時對其數據進行讀寫和修改的能力,隔離性可以防止多個事務併發執行時,由於交叉執行而導致數據的不一致。
- 持久性 durability:事務處理結束後,對數據的修改就是持久的,即便系統故障也不會丟失。
在數據庫系統中,一個事務指:由一系列數據庫操作組成的一個完整的邏輯過程。如銀行轉賬,從原賬戶扣除金額、向目標賬戶添加金額,這兩個數據庫操作的總和構成一個完整的邏輯過程,不可拆分。這個過程被稱爲一個事務,具有ACID特性。
3. 安裝 SQLite
在命令後輸入sqlite3
即可查看是否安裝了SQLite
:
$ sqlite3
SQLite version 3.28.0 2019-04-15 14:49:49
Enter ".help" for usage hints.
Connected to a transient in-memory database.
Use ".open FILENAME" to reopen on a persistent database.
sqlite>
Linux 和 macOS 預裝了 SQLite。如果你的操作系統沒有預裝 SQLite,訪問SQLite 下載頁面根據提示安裝即可。
4. 點命令
這一部分介紹 SQLite 的點命令,其不以分號結束。
輸入.help
可獲取點命令清單。如下所示:
sqlite> .help
.databases List names and files of attached databases
.mode MODE ?TABLE? Set output mode
.quit Exit this program
.save FILE Write in-memory database into FILE
.schema ?PATTERN? Show the CREATE statements matching PATTERN
.show Show the current values for various settings
.stats ?on|off? Show stats or turn stats on or off
.tables ?TABLE? List names of tables matching LIKE pattern TABLE
.timeout MS Try opening locked tables for MS milliseconds
.timer on|off Turn SQL timer on or off
.width NUM1 NUM2 ... Set column widths for "column" mode\
...
可以使用下面點命令自定義輸出格式:
sqlite> .header on
sqlite> .mode column
sqlite> .timer on
上面設置將產生如下格式的輸出:
ID NAME AGE ADDRESS SALARY
---------- ---------- ---------- ---------- ----------
1 Paul 32 California 20000.0
2 Allen 25 Texas 15000.0
3 Teddy 23 Norway 20000.0
4 Mark 25 Rich-Mond 65000.0
5 David 27 Texas 85000.0
6 Kim 22 South-Hall 45000.0
7 James 24 Houston 10000.0
Run Time: real 0.001 user 0.000113 sys 0.000087
5. 數據類型
SQLite 使用一個更普遍的動態類型系統,值的數據類型與值本身是相關的,與其容器無關。
5.1 存儲類
每個存儲在 SQLite 數據庫中的值都具有以下存儲類之一:
存儲類 | 描述 |
---|---|
NULL | 值是一個 NULL 值。 |
INTEGER | 值是一個帶符號的整數。根據值大小存儲在1、2、3、4、6或8個字節中。 |
REAL | 值是一個浮點值。存儲爲8個字節的 IEEE 浮點數字。 |
TEXT | 值是一個文本字符串,使用數據庫編碼(UTF-8、UTF-16BE或 UTF-16LE)存儲。 |
BLOB | 完全根據輸入存儲。 |
存儲類比數據類稍微普遍些。例如,INTEGER 存儲類包含六種不同長度的整數數據類型。
5.2 親和類型 Affinity
SQLite 支持親和類型概念,列內可以存儲任何類型的數據。當數據插入時,該字段的數據將會優先採用親緣類型作爲該值的存儲方式。目前支持以下五種親緣類型:
親和類型 | 描述 |
---|---|
TEXT | 數值型數據在被插入之前,需要先被轉換爲文本格式再插入到目標字段中。 |
NUMERIC | 當文本數據被插入到親緣性爲NUMERIC的字段中時,如果轉換操作不會導致信息丟失以及完全可逆,會將文本數據轉換爲INTEGER或REAL類型數據,如果轉換失敗,仍會以TEXT方式存儲該數據; NULL和BLOB類型數據,不做任何轉換,直接存儲; 浮點格式的常量文本,如 3000.0 。如果該值可以轉換爲INTEGER,同時又不丟失數值信息,則會轉爲INTEGER存儲。 |
INTEGER | 規則與NUMERIC相同,唯一差別在執行CAST表達式。 |
REAL | 規則基本等同於NUMERIC。唯一差別是不會將3000.0 這樣的文本數據轉換爲INTEGER存儲。 |
NONE | 不做任何轉換,直接以該數據所屬的數據類型進行存儲。 |
5.3 數據類型與親和類型對照
下面列出了數據類型和親和類型的對應關係:
親和類型 | 數據類型 |
---|---|
INTEGER | INT、INTEGER、TINYINT、SMALLINT、MEDIUMINT、BEGINT、UNSIGNED BIG INT、INT2、INT8 |
TEXT | CHARACTER(20)、VARCHAR(255)、VARYING CHARACTER(255)、NCHAR(55)、NATIVE CHARACTER(70)、NVARCHAR(100)、TEXT、CLOB |
NONE | BLOB、no datatype specified |
REAL | REAL、DOUBLE、DOUBLE PRECISION、FLOAT |
NUMERIC | NUMERIC、DECIMAL(10.5)、BOOLEAN、DATEDATETIME |
SQLite 沒有單獨 Boolean 存儲類。布爾值被存儲爲整數0和1。也沒有日期、時間存儲類,將日期、時間存儲爲TEXT、REAL或INTEGER值。
6. 創建數據庫
6.1 語法
使用sqlite3
命令創建數據庫,語法如下:
$ sqlite3 DatabaseName.db
6.2 示例
如果想創建名稱爲LearnDB.db
的數據庫,命令如下:
$ sqlite3 LearnDB.sql
SQLite version 3.28.0 2019-04-15 14:49:49
Enter ".help" for usage hints.
sqlite>
數據庫名稱應唯一。
與其他數據庫管理系統不同,SQLite 不支持 DROP DATABASE 語句。如果想要刪除數據庫,直接刪除文件即可。
7. 表 Table
7.1 創建表
CREATE TABLE
語句用於創建表。創建時指定表名稱,定義列以及每列數據類型。
7.1.1 語法
CREATE TABLE 語法如下:
CREATE TABLE table_name(
column1 datatype PRIMARY KEY,
column2 datatype,
column3 datatype,
...
columnN datatype,
);
7.1.2 示例
下面創建了一個 COMPANY 表,ID 作爲主鍵,NOT NULL 約束標記字段不能爲 NULL:
sqlite> CREATE TABLE COMPANY(
...> ID INT PRIMARY KEY NOT NULL,
...> NAME TEXT NOT NULL,
...> AGE INT NOT NULL,
...> ADDRESS CHAR(50),
...> SALARY REAL
...> );
再創建一個 CLASS 表,以便後續部分使用:
sqlite> CREATE TABLE CLASS(
...> ID INT PRIMARY KEY NOT NULL,
...> NAME TEXT NOT NULL,
...> CLASS_ID INT NOT NULL
...> );
.tables
命令可以列出數據庫中的所有表:
sqlite> .tables
CLASS COMPANY
.schema
命令可以查看錶的完整信息:
sqlite> .schema
CREATE TABLE COMPANY(
ID INT PRIMARY KEY NOT NULL,
NAME TEXT NOT NULL,
AGE INT NOT NULL,
ADDRESS CHAR(50),
SALARY REAL
);
7.2 刪除表
DROP TABLE 語句刪除使用 CREATE TABLE 語句創建的表,刪除的表會徹底從數據庫、文件中移除,不可恢復。表關聯的索引、觸發器、約束會被同步刪除。
7.2.1 語法
DROP TABLE 語句語法如下:
DROP TABLE IF EXISTS table-name
可選的 IF EXISTS 子句可抑制表不存在導致的錯誤。
7.2.2 示例
先確認 CLASS 表存在,再將其刪除:
sqlite> .tables
CLASS COMPANY
sqlite> DROP TABLE IF EXISTS CLASS;
sqlite> .tables
COMPANY
現在已經無法找到 CLASS 表了。
8. 插入 INSERT
INSERT INTO 語句用於向表中添加新的行。
8.1 語法
INSERT INTO 語句有兩種語法,如下所示:
// 第一種
INSERT INTO TABLE_NAME [(column1, column2, column3, ... columnN)]
VALUES (value1, value2, value3, ... valueN);
// 第二種
INSERT INTO TABLE_NAME VALUES (value1, value2, value3, ... valueN);
column1、column2 是要插入數據列的名稱。如果要爲所有列添加值,可以使用第二種方式,但值順序必須與列在表中的順序一致。
8.2 示例
LearnDB.sql 數據庫中已經有了 COMPANY 表,如下所示:
sqlite> .schema
CREATE TABLE COMPANY(
ID INT PRIMARY KEY NOT NULL,
NAME TEXT NOT NULL,
AGE INT NOT NULL,
ADDRESS CHAR(50),
SALARY REAL
);
使用以下語句在表中創建七條記錄:
sqlite> INSERT INTO COMPANY (ID, NAME, AGE, ADDRESS, SALARY)
...> VALUES (1, 'Paul', 32, 'California', 20000.00 );
sqlite> INSERT INTO COMPANY (ID, NAME, AGE, ADDRESS, SALARY)
...> VALUES (2, 'Allen', 25, 'Texas', 15000.00 );
sqlite> INSERT INTO COMPANY (ID, NAME, AGE, ADDRESS, SALARY)
...> VALUES (3, 'Teddy', 23, 'Norway', 20000.00 );
sqlite> INSERT INTO COMPANY (ID, NAME, AGE, ADDRESS, SALARY)
...> VALUES (4, 'Mark', 25, 'Rich-Mond', 65000.00 );
sqlite> INSERT INTO COMPANY (ID, NAME, AGE, ADDRESS, SALARY)
...> VALUES (5, 'David', 27, 'Texas', 85000.00 );
sqlite> INSERT INTO COMPANY (ID, NAME, AGE, ADDRESS, SALARY)
...> VALUES (6, 'Kim', 22, 'South-Hall', 45000.00 );
sqlite> INSERT INTO COMPANY VALUES (7, 'James', 24, 'Houston', 10000.00 );
目前表記錄如下:
sqlite> SELECT * FROM COMPANY;
ID NAME AGE ADDRESS SALARY
---------- ---------- ---------- ---------- ----------
1 Paul 32 California 20000.0
2 Allen 25 Texas 15000.0
3 Teddy 23 Norway 20000.0
4 Mark 25 Rich-Mond 65000.0
5 David 27 Texas 85000.0
6 Kim 22 South-Hall 45000.0
7 James 24 Houston 10000.0
Run Time: real 0.001 user 0.000113 sys 0.000087
8.3 使用一個表來填充另一個表
還可以通過在有一組字段的表上使用 select 語句,填充數據到另一個表中。如下所示:
sqlite> INSERT INTO target_table_name [(column1, column2, ... columnN)]
...> SELECT column1, column2, ... columnN
...> FROM source_table_name
...> [WHERE condition];
9. 查詢 SELECT
SELECT 語句用於從數據庫中獲取數據,以表的形式返回數據。
9.1 語法
SELECT 語句基本語法如下:
SELECT column1, column2, columnN FROM table_name;
column1、column2... 是表的字段,即想要獲取的值。如果想要獲取所有字段,使用下面語句:
SELECT * FROM table_name;
9.2 示例
使用SELECT語句獲取 COMPANY 表所有記錄:
sqlite> SELECT * FROM COMPANY;
ID NAME AGE ADDRESS SALARY
---------- ---------- ---------- ---------- ----------
1 Paul 32 California 20000.0
2 Allen 25 Texas 15000.0
3 Teddy 23 Norway 20000.0
4 Mark 25 Rich-Mond 65000.0
5 David 27 Texas 85000.0
6 Kim 22 South-Hall 45000.0
7 James 24 Houston 10000.0
Run Time: real 0.000 user 0.000108 sys 0.000096
如果只想獲取指定字段,使用以下語句:
sqlite> SELECT ID, NAME, ADDRESS FROM COMPANY;
ID NAME ADDRESS
---------- ---------- ----------
1 Paul California
2 Allen Texas
3 Teddy Norway
4 Mark Rich-Mond
5 David Texas
6 Kim South-Hall
7 James Houston
Run Time: real 0.000 user 0.000145 sys 0.000109
9.3 Schema 信息
點命令只能在 SQLite 提示符中使用,編程時如需列出數據庫中所有的表,使用以下語句:
sqlite> SELECT tbl_name FROM sqlite_master WHERE type = 'table';
tbl_name
----------
COMPANY
Run Time: real 0.001 user 0.000101 sys 0.000142
如需獲取 COMPANY 完整信息,使用以下語句:
sqlite> SELECT sql FROM sqlite_master WHERE type = 'table' AND tbl_name = 'COMPANY';
sql
--------------------------------------------------------------------------------------
CREATE TABLE COMPANY(
ID INT PRIMARY KEY NOT NULL,
NAME TEXT NOT NULL,
AGE INT NOT NULL,
ADDRESS CHAR(50),
SALARY REAL
)
Run Time: real 0.000 user 0.000082 sys 0.000073
10. 運算符
運算符是一個保留字、字符,主要用於 WHERE 子句中執行操作。
10.1 算數運算符
支持的算數運算符有+、-、*、/、%五種,
10.2 比較運算符
比較運算符支持以下類型:
- == 檢查操作數值是否相等。如果相等則條件爲真。
- = 與 == 一樣。
- != 檢查操作數值是否相等。如果不相等則條件爲真。
- <> 與 != 一樣。
- 此外,還支持>、<、>=、<=、!<、!>。
10.3 邏輯運算符
邏輯運算符支持以下類型:
- AND:允許 WHERE 子句存在多個條件,均成立時,子句爲真。
- BETWEEN:指定值範圍。
- EXISTS:用於在滿足一定條件的指定表中搜索行是否存在。
- IN:用於把指定值與一系列值進行比較。
- NOT IN:IN 的對立面。
- LIKE:將指定值與使用通配符的值進行比較。
- GLOB:與 LIKE 類似,但 GLOB 區分大小寫。
- NOT:否定運算符,
- OR:允許 WHERE 子句存在多個條件,有一個成立即爲真。
- IS NULL:與 NULL 比較。
- IS:與 = 相似。
- IS NOT:與 != 相似。
- || :連接兩個不同的字符串,得到一個新的字符串。
- UNIQUE:搜索表中的每一行,確保無重複。
11. WHERE
WHERE 指定獲取數據的條件。表中每一行均會與 WHERE 表達式匹配,只有表達式爲真時,才返回指定值。
11.1 語法
帶有 WHERE 子句的 SELECT 語句的基本語法如下:
SELECT column1, column2, columnN
FROM table_name
WHERE [condition]
11.2 示例
下面的 SELECT 語句列出了 COMPANY 表 AGE 大於等於25且工資大於等於65000.00的所有記錄:
sqlite> SELECT * FROM COMPANY WHERE AGE >= 25 AND SALARY >= 65000.00;
ID NAME AGE ADDRESS SALARY
---------- ---------- ---------- ---------- ----------
4 Mark 25 Rich-Mond 65000.0
5 David 27 Texas 85000.0
Run Time: real 0.005 user 0.000316 sys 0.002061
下面 SELECT 語句列出了 COMPANY 表 NAME 以 'Ki' 開始的所有記錄,‘Ki’之後字符不做限制:
sqlite> SELECT * FROM COMPANY WHERE NAME LIKE 'KI%';
ID NAME AGE ADDRESS SALARY
---------- ---------- ---------- ---------- ----------
6 Kim 22 South-Hall 45000.0
Run Time: real 0.000 user 0.000130 sys 0.000155
下面的 SELECT 語句,子查詢查找 SALARY > 65000 的帶有 AGE 字段的所有記錄,後邊的 WHERE 子句與 EXISTS 運算符一起使用,列出了外查詢中的 AGE 存在於子查詢返回的結果中的所有記錄:
sqlite> SELECT AGE FROM COMPANY
...> WHERE EXISTS (SELECT AGE FROM COMPANY WHERE SALARY > 65000);
AGE
----------
32
25
23
25
27
22
24
Run Time: real 0.000 user 0.000112 sys 0.000128
WHERE子句不僅可以用在 SELECT 語句中,還可以用在UPDATE、DELETE語句中。
12. 更新 UPDATE
UPDATE 語句用於修改表中的零行、多行的值。
12.1 語法
UPDATE 語句基本語法如下:
UPDATE table_name
SET column1 = value1, column2 = value2 ..., columnN = valueN
WHERE [condition];
WHERE 子句可以組合使用運算符。如果沒有 WHERE 子句,則修改所有行的值;反之,只修改 WHERE 子句爲真的行。
SET 關鍵字後賦值語句決定修改哪些字段。每個賦值語句左側指定要修改的字段,右側指定值。如果單個字段名稱出現多次,則只採取最後一次設置的值,並忽略前面所有賦值。未出現字段名稱的行,值保持不變。WHERE 表達式可能引用要更新的行,此時會先評估所有表達式,再進行賦值。
12.2 示例
下面語句會更新 ID 爲6的客戶地址:
sqlite> SELECT * FROM COMPANY;
ID NAME AGE ADDRESS SALARY
---------- ---------- ---------- ---------- ----------
1 Paul 32 California 20000.0
2 Allen 25 Texas 15000.0
3 Teddy 23 Norway 20000.0
4 Mark 25 Rich-Mond 65000.0
5 David 27 Texas 85000.0
6 Kim 22 South-Hall 45000.0
7 James 24 Houston 10000.0
Run Time: real 0.000 user 0.000145 sys 0.000097
sqlite> UPDATE COMPANY SET ADDRESS = 'Texas' WHERE ID = 6;
Run Time: real 0.004 user 0.000165 sys 0.003125
sqlite> SELECT * FROM COMPANY;
ID NAME AGE ADDRESS SALARY
---------- ---------- ---------- ---------- ----------
1 Paul 32 California 20000.0
2 Allen 25 Texas 15000.0
3 Teddy 23 Norway 20000.0
4 Mark 25 Rich-Mond 65000.0
5 David 27 Texas 85000.0
6 Kim 22 Texas 45000.0
7 James 24 Houston 10000.0
Run Time: real 0.000 user 0.000160 sys 0.000160
可以看到地址信息更新前爲”South-Hall“,更新後爲“Texas”。
13. 刪除 DELETE
DELETE 語句用於刪除表中已有記錄。
13.1 語法
DELETE FROM table_name
WHERE [condition];
如果沒有 WHERE 子句,則刪除所有記錄;如果提供了 WHERE 子句,則僅刪除子句表達式爲true的行,表達式爲false或NULL的行會被保留。
13.2 示例
下面語句會刪除 ID 爲7的客戶:
sqlite> DELETE FROM COMPANY WHERE ID = 7;
Run Time: real 0.002 user 0.000128 sys 0.001266
sqlite> SELECT * FROM COMPANY;
ID NAME AGE ADDRESS SALARY
---------- ---------- ---------- ---------- ----------
1 Paul 32 California 20000.0
2 Allen 25 Texas 15000.0
3 Teddy 23 Norway 20000.0
4 Mark 25 Rich-Mond 65000.0
5 David 27 Texas 85000.0
6 Kim 22 Texas 45000.0
Run Time: real 0.001 user 0.000166 sys 0.000179
下一篇文章SQLite的使用二將繼續介紹SQLite的用法。
歡迎更多指正:https://github.com/pro648/tips
本文地址:https://github.com/pro648/tips/blob/master/sources/SQLite%E7%9A%84%E4%BD%BF%E7%94%A8%E4%B8%80.md