Android SQLite (三 ) 全面詳解(一)


官網 SQLite是一款輕型的數據庫,是關系型數據庫(RDBMS)管理系統,它包含在一個相對小的C庫中。目前在很多嵌入式產品中使用了它,它占用資源非常 的低,在嵌入式設備中,可能只需要幾百K的內存就夠了。它能夠支持Windows/Linux/Unix/Android/IOS等等主流的操作系統,同 時能夠跟很多程序語言相結合,比如 Tcl、C#、PHP、Java等,還有ODBC接口,同樣比起Mysql、PostgreSQL這兩款開源的世界著名數據庫管理系統來講,它的處理速度 比他們都快。

Sqlite命令分類:

(DDL)數據定義語言:

CMD Description
CREATE 創建一個新的表,一個表的視圖,或者數據庫中的其他對象。
ALTER 修改數據庫中的某個已有的數據庫對象,比如一個表。
DROP 刪除整個表,或者表的視圖,或者數據庫中的其他對象。


(DML)數據操作語言:

CMD Description
INSERT 創建一條記錄。
UPDATE 修改記錄。
DELETE 刪除記錄。


(DQL)數據查詢語言:

CMD Description
SELECT 從一個或多個表中檢索某些記錄。

Sqlite點命令

先看一張Windows下的截圖:
這里寫圖片描述

這是在Windows的cmd下運行sqlite3命令(如何安裝和配置煩請自行google | baidu),然后依據提示運行.help的打印(只截圖一部分)。

可以發現sqlite的help列出來了所有sqlite支持的點命令,也可以發現,點命令不需要已”;”結尾。

我們對上面的.help命令進行翻譯大致如下:

CMD Description
.backup ?DB? FILE 備份DB數據庫(默認是”main”)到FILE文件。
.bail ON/OFF 發生錯誤后停止。默認為OFF。
.databases 列出附加數據庫的名稱和文件。
.dump ?TABLE? 以SQL文本格式轉儲數據庫。如果指定了TABLE表,則只轉儲匹配LIKE模式的TABLE表。
.echo ON/OFF 開啟或關閉echo命令。
.exit 退出SQLite提示符。
.explain ON/OFF 開啟或關閉適合於EXPLAIN的輸出模式。如果沒有帶參數,則為EXPLAIN on,及開啟EXPLAIN。
.header(s) ON/OFF 開啟或關閉頭部顯示。
.help 顯示消息。
.import FILE TABLE 導入來自FILE文件的數據到TABLE表中。
.indices ?TABLE? 顯示所有索引的名稱。如果指定了TABLE表,則只顯示匹配LIKE模式的TABLE表的索引。
.load FILE ?ENTRY? 加載一個擴展庫。
.log FILE/off 開啟或關閉日志。FILE文件可以是stderr(標准錯誤)/stdout(標准輸出)。
.mode MODE 設置輸出模式,MODE可以是下列之一:csv 逗號分隔的值;column 左對齊的列;html HTML的<table>代碼;insert TABLE表的SQL插入(insert)語句;line 每行一個值;list 由 .separator字符串分隔的值;tabs 由Tab分隔的值;tcl TCL列表元素。
.nullvalue STRING 在NULL值的地方輸出STRING字符串。
.output FILENAME 發送輸出到FILENAME文件。
.output stdout 發送輸出到屏幕。
.print STRING... 逐字地輸出STRING字符串。
.prompt MAIN CONTINUE 替換標准提示符。
.quit 退出SQLite提示符。
.read FILENAME 執行FILENAME文件中的SQL。
.schema ?TABLE? 顯示CREATE語句。如果指定了TABLE表,則只顯示匹配LIKE模式的TABLE表。
.separator STRING 改變輸出模式和.import所使用的分隔符。
.show 顯示各種設置的當前值。
.stats ON/OFF 開啟或關閉統計。
.tables ?PATTERN? 列出匹配LIKE模式的表的名稱。
.timeout MS 嘗試打開鎖定的表MS微秒。
.width NUM NUM 為”column”模式設置列寬度。
.timer ON/OFF 開啟或關閉CPU定時器測量。

Sqlite數據庫的sqlite_master表

主表中保存數據庫表的關鍵信息,並把它命名為sqlite_master。如要查看表概要,可如下操作:

sqlite>.schema sqlite_master

Sqlite語法規則

SQLite是遵循一套獨特的稱為語法的規則和准則。

SQLite是不區分大小寫的,但也有一些命令是大小寫敏感的,比如GLOB和glob在SQLite的語句中有不同的含義。

SQLite 注釋是附加的注釋,可以在 SQLite 代碼中添加注釋以增加其可讀性,他們可以出現在任何空白處,包括在表達式內和其他 SQL 語句的中間,但它們不能嵌套。

SQL注釋以兩個連續的”-“字符開始,並擴展至下一個換行符或直到輸入結束,以先到者為准。也可以以”/*"開始,並擴展至下一個 “*/” 字符對或直到輸入結束,以先到者為准。SQLite的注釋可以跨越多行。

SQLite語句以任何關鍵字開始,以”;”結束。

Sqlite數據類型

SQLite數據類型是一個用來指定任何對象的數據類型的屬性。SQLite 中的每一列,每個變量和表達式都有相關的數據類型。您可以在創建表的同時使用這些數據類型。SQLite使用一個更普遍的動態類型系統。在SQLite 中,值的數據類型與值本身是相關的,而不是與它的容器相關。

存儲類

SQLite有5個原始的數據類型,被稱為存儲類。存儲類這個詞表明了一個值在磁盤上存儲的格式,其實就是類型或數據類型的同義詞。如下即是存儲類:

存儲類 Description
NULL 值是一個NULL值。
INTEGER 值是一個帶符號的整數,根據值的大小存儲在1、2、3、4、6 或8字節中。
REAL 值是一個浮點值,存儲為8字節的IEEE浮點數字。
TEXT 值是一個文本字符串,使用數據庫編碼(UTF-8、UTF-16BE或UTF-16LE)存儲。
BLOB 值是一個blob數據,完全根據它的輸入存儲。


SQLite通過值的表示法來判斷其類型,下面就是SQLite的推理方法:

  • SQL語句中用單引號或雙引號括起來的文字被指派為TEXT。
  • 如果文字是未用引號括起來的數據,並且沒有小數點和指數,被指派為INTEGER。
  • 如果文字是未用引號括起來的數據,並且帶有小數點或指數,被指派為REAL。
  • 用NULL說明的值被指派為NULL存儲類。
  • 如果一個值的格式為X’ABCD’,其中ABCD為16進制數字,則該值被指派為BLOB。X前綴大小寫皆可。

如下就是驗證結果:
這里寫圖片描述

SQLite單獨的一個字段可能包含不同存儲類的值。

如下就是驗證結果:
這里寫圖片描述

喜歡鑽牛角尖的這時候指定開始BB了,temp這一列數據類型不同,咋樣比較大小?咋樣排序等等?

經過查閱資料發現,具有不同存儲類的值可以存儲在同一個字段中。可以被排序,因為這些值可以相互比較。有完善定義的規則來做這件事。不同存儲類的值可以通過它們各自類的“類值”進行排序,定義如下:

  • NULL存儲類具有最低的類值。一個具有NULL存儲類的值比所有其它值都小(包括其它具有NULL存儲類的值)。在NULL值之間,沒有特別的可排序值。
  • INTEGER或REAL存儲類值高於NULL,它們的類值相等。INTEGER值和REAL值通過其數值進行比較。
  • TEXT存儲類的值比INTEGER和REAL高。數值永遠比字符串的值低。當兩個TEXT值進行比較時,其值大小由“排序法”決定。
  • BLOB存儲類具有最高的類值。具有BLOB類的值大於其它所有類的值。BLOB值之間在比較時使用C函數memcmp()。

所以,當SQLite對一個字段進行排序時,首先按存儲類排序,然后再進行類內的排序 (NULL類內部各值不必排序) 。

弱類型(manifest typing)

首先有如下SQL語句:

CREATE TABLE table_yanbo( x integer, y text, z real ); INSERT INTO table_yanbo VALUES ('1', '1', '1');

這里的x、y和z這3個字段中存儲的是INTEGER, TEXT和REAL類型。

再看下面例子:

CREATE TABLE table_yanbo(x, y, z); INSERT INTO table_yanbo VALUES ('1', '1', '1');

這里的x、y和z這3個字段中存儲的是TEXT、TEXT和TEXT類型。

再看下面例子:

CREATE TABLE table_yanbo(x, y, z); INSERT INTO table_yanbo VALUES (1, 1.0, x'10');

這里的x、y和z這3個字段中存儲的是INTEGER、REAL和BLOB類型。

通過上面幾種寫法你會發現,可以為SQLite的字段定義類型,但這不是必須的,你可以盡管違反類型定義。這是因為在任何情況下,SQLite都可以接受一個值並推斷它的類型。

總之,SQLite的弱類型可表示為:

  1. 字段可以有類型。
  2. 類型可以通過值來推斷。

類型親和性介紹這兩個規定如何相互關聯。所謂類型親和性就是在強類型(strict typing)和動態類型(dynamic typing)之間的平衡藝術。

類型親和性(Type Affinity)

在SQLite中,字段沒有類型或域。當給一個字段聲明了類型,該字段實際上僅僅具有了該類型的親和性。聲明類型和類型親和性是兩回事。類型親和性 預定SQLite用什么存儲類在字段中存儲值。在存儲一個給定的值時到底SQLite會在該字段中用什么存儲類決定於值的存儲類和字段親和性的結合。

任何列可以存儲任何類型的數據,但列的首選存儲類是它的affinity。在SQLite3數據庫中,每個表的列分配為以下類型的affinity之一:

Affinity Description
TEXT 該列使用存儲類NULL、TEXT或BLOB存儲所有數據。
NUMERIC 該列可以包含使用所有五個存儲類的值。
INTEGER 與帶有NUMERIC affinity的列相同,在CAST表達式中帶有異常。
REAL 與帶有NUMERIC affinity的列相似,不同的是,它會強制把整數值轉換為浮點表示。
NONE 帶有affinity NONE的列,不會優先使用哪個存儲類,也不會嘗試把數據從一個存儲類強制轉換為另一個存儲類。


下表列出了當創建SQLite3表時可使用的各種數據類型名稱,同時也顯示了相應的應用Affinity:

數據類型 Affinity
INT、NTEGER、TINYINT、SMALLINT、MEDIUMINT、BIGINT、UNSIGNED BIG INT、INT2、INT8 INTEGER
CHARACTER(20)、VARCHAR(255)、VARYING CHARACTER(255)、NCHAR(55)、NATIVE CHARACTER(70)、NVARCHAR(100)、TEXT、CLOB TEXT
BLOB、no datatype specified NONE
REAL、DOUBLE、DOUBLE PRECISION、FLOAT REAL
NUMERIC、DECIMAL(10,5)、BOOLEAN、DATE、DATETIME NUMERIC


Boolean數據類型

SQLite沒有單獨的Boolean存儲類,布爾值被存儲為整數 0(false)和 1(true)。

Date與Time數據類型

SQLite沒有一個單獨的用於存儲日期和/或時間的存儲類,但SQLite 能夠把日期和時間存儲為TEXT、REAL或 INTEGER值。您可以以任何上述格式來存儲日期和時間,並且可以使用內置的日期和時間函數來自由轉換不同格式。

存儲類 日期格式
TEXT 格式為”YYYY-MM-DD HH:MM:SS.SSS”的日期。
REAL 從公元前4714年11月24日格林尼治時間的正午開始算起的天數。
INTEGER 從1970-01-01 00:00:00 UTC算起的秒數。


字段類型和親和性

首先,每個字段都具有一種親和性。共有五種親和性:NUMERIC、INTEGER、REAL、TEXT和NONE。一個字段的親和性由它預聲明的類型決定。所以,當你為字段聲明了類型,從根本上說是為字段指定了親和性。SQLite按下面的規則為字段指派親和性:

  • 默認的,一個字段默認的親和性是NUMERIC。如果一個字段不是INTEGER、TEXT、REAL或NONE的,那它自動地被指派為NUMERIC親和性。
  • 如果為字段聲明的類型中包含了’INT’(無論大小寫),該字段被指派為INTEGER親和性。
  • 如果為字段聲明的類型中包含了’CHAR’、’CLOB’或’TEXT’(無論大小寫),該字段被指派為TEXT親和性。如’VARCHAR’包含了’CHAR’,所以被指派為TEXT親和性。
  • 如果為字段聲明的類型中包含了’BLOB’(無論大小寫),或者沒有為該字段聲明類型,該字段被指派為NONE親和性。

注意:如果沒有為字段聲明類型,該字段的親和性為NONE,在這種情況下,所有的值都將以它們本身的(或從它們的表示法中推斷的)存儲類存儲。如果 你暫時還不確定要往一個字段里放什么內容,或准備將來修改,用NONE親和性是一個好的選擇。但SQLite默認的親和性是NUMERIC。例如,如果為 一定字段聲明了類型JUJYFRUIT,該字段的親和性不是NONE,因為SQLite不認識這種類型,會給它指派默認的NUMERIC親和性。所以,與 其用一個不認識的類型最終得到NUMERIC親和性,還不如不為它指定類型,從而使它得到NONE親和性。

親和性和存儲

親和性對值如何存儲到字段有影響,規則如下:

  • 一個NUMERIC字段可能包括所有5種存儲類。一個NUMERIC字段具有數字存儲類的偏好(INTEGER和REAL)。當一個TEXT值被 插入到一個NUMERIC字段,將會試圖將其轉化為INTEGER存儲類;如果轉化失敗,將會試圖將其轉化為REAL存儲類;如果還是失敗,將會用 TEXT存儲類來存儲。
  • 一個INTEGER字段的處理很像NUMERIC字段。一個INTEGER字段會將REAL值按REAL存儲類存儲。也就是說,如果這個REAL 值沒有小數部分,就會被轉化為INTEGER存儲類。INTEGER字段將會試着將TEXT值按REAL存儲;如果轉化失敗,將會試圖將其轉化為 INTEGER存儲類;如果還是失敗,將會用TEXT存儲類來存儲。
  • 一個TEXT字段將會把所有的INTEGER或REAL值轉化為TEXT。
  • 一個NONE字段不試圖做任何類型轉化。所有值按它們本身的存儲類存儲。
  • 沒有字段試圖向NULL或BLOB值轉化——如無論用什么親和性。NULL和BLOB值永遠都按本來的方式存儲在所有字段。

這些規則初看起來比較復雜,但總的設計目標很簡單,如果你需要,SQLite會盡量模仿其它的關系型數據庫。也就是說,如果你將SQLite看成是 一個傳統數據庫,類型親和性將會按你的期望來存儲值。如果你聲明了一個INTEGER字段,並向里面放一個整數,就會按整數來存儲。如果你聲明了一個具有 TEXT, CHAR或VARCHAR類型的字段並向里放一個整數,整數將會轉化為TEXT。可是,如果你不遵守這些規定,SQLite也會找到辦法來存儲你的值。

如下例子展示了親和性是如何工作的:
這里寫圖片描述

存儲類和類型轉換

關於存儲類,需要關注的另一件事是存儲類有時會影響到值如何進行比較。特別是SQLite有時在進行比較之前,會將值在數字存儲類(INTEGER和REAL)和TEXT之間進行轉換。為進行二進制的比較,遵循如下規則:

  • 當一個字段值與一個表達式的結果進行比較,字段的親和性會在比較之前應用於表達式的結果。
  • 當兩個字段值進行比較,如果一個字段擁有INTEGER或NUMERIC親和性而另一個沒有,NUMERIC親和性會應用於非NUMERIC字段的TEXT值。
  • 當兩個表達式進行比較,SQLite不做任何轉換。如果兩個表達式有相似的存儲類,則直接按它們的值進行比較;否則按類值進行比較。

總結

這里主要介紹了Sqlite的一些基本概念和數據類型的特性。關於Sqlite其他內容接下來文章繼續介紹。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM