SQLite的使用一

這是SQLite系列文章第一篇。

  1. SQLite的使用一
  2. SQLite的使用二
  3. 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

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章