SQLite的SQL語法 SQLite的SQL語法 SQLite庫可以解析大部分標準SQL語言。但它也省去了一些特性並且加入了一些自己的新特性。這篇文檔就是試圖描述那些SQLite支持/不支持的SQL語法的。查看關鍵字列表。 如下語法表格中,純文本用藍色粗體顯示。非終極符號為斜體紅色。作為語法一部分 ...
SQLite的SQL語法
SQLite庫可以解析大部分標準SQL語言。但它也省去了一些特性並且加入了一些自己的新特性。這篇文檔就是試圖描述那些SQLite支持/不支持的SQL語法的。查看關鍵字列表。
如下語法表格中,純文本用藍色粗體顯示。非終極符號為斜體紅色。作為語法一部分的運算符用黑色Roman字體表示。
這篇文檔只是對SQLite實現的SQL語法的綜述,有所忽略。想要得到更詳細的信息,參考源代碼和語法文件“parse.y”。
SQLite執行如下的語法:
- ALTER TABLE
- ANALYZE
- ATTACH DATABASE
- BEGIN TRANSACTION
- 註釋
- COMMIT TRANSACTION
- COPY
- CREATE INDEX
- CREATE TABLE
- CREATE TRIGGER
- CREATE VIEW
- DELETE
- DETACH DATABASE
- DROP INDEX
- DROP TABLE
- DROP TRIGGER
- DROP VIEW
- END TRANSACTION
- EXPLAIN
- 表達式
- INSERT
- ON CONFLICT子句
- PRAGMA
- REINDEX
- REPLACE
- ROLLBACK TRANSACTION
- SELECT
- UPDATE
- VACUUM
ALTER TABLE
sql-statement ::= | ALTER TABLE [database-name .] table-name alteration |
alteration ::= | RENAME TO new-table-name |
alteration ::= | ADD [COLUMN] column-def |
SQLite版本的的ALTER TABLE命令允許用戶重命名或添加新的欄位到已有表中,不能從表中刪除欄位。
RENAME TO語法用於重命名錶名[database-name.]table-name到new-table-name。這一命令不能用於在附加資料庫之間移動表,只能在同一個資料庫中對錶進行重命名。
若需要重命名的表有觸發器或索引,在重命名後它們依然屬於該表。但若定義了視圖,或觸發器執行的語句中有提到 表的名字,則它們不會被自動改為使用新的表名。若要進行這一類的修改,則需手工撤銷並使用新的表名重建觸發器或視圖。
ADD [COLUMN]語法用於在已有表中添加新的欄位。新欄位總是添加到已有欄位列表的末尾。Column-def可以是CREATE TABLE中允許出現的任何形式,且須符合如下限制:
- 欄位不能有主鍵或唯一約束。
- 欄位不能有這些預設值:CURRENT_TIME, CURRENT_DATE或CURRENT_TIMESTAMP
- 若定義了NOT NULL約束,則欄位必須有一個非空的預設值。
ALTER TABLE語句的執行時間與表中的數據量無關,它在操作一個有一千萬行的表時的運行時間與操作僅有一行的表時是一樣的。
在對資料庫運行ADD COLUMN之後,該資料庫將無法由SQLite 3.1.3及更早版本讀取,除非運行VACUUM命令。
ANALYZE
sql-statement ::= | ANALYZE |
sql-statement ::= | ANALYZE database-name |
sql-statement ::= | ANALYZE [database-name .] table-name |
ANALYZE命令令集合關於索引的統計信息並將它們儲存在資料庫的一個特殊表中,查詢優化器可以用該表來製作更好的索引選擇。若不給出參數,所有附加資料庫中的所有索引被分析。若參數給出資料庫名,該資料庫中的所有索引被分析。若給出表名 作參數,則只有關聯該表的索引被分析。
最初的實現將所有的統計信息儲存在一個名叫sqlite_stat1的表中。未來的加強版本中可能會創建名字類似的其它表,只是把“1”改為其它數字。sqlite_stat1表不能夠被撤銷,但其中的所有內容可以被刪除,這是與撤銷該表等效的行為。
ATTACH DATABASE
ATTACH DATABASE語句將一個已存在的資料庫添加到當前資料庫連接。若文件名含標點符號,則應用引號引起來。資料庫名’main’和’temp’代表主資料庫和用於存放臨時表的資料庫,它們不能被拆分。拆分資料庫使用DETACH DATABASE語句。
你可以讀寫附加資料庫,或改變其結構。這是SQLite 3.0提供的新特性。在SQLite 2.8中,改變附加資料庫的結構是不允許的。
在附加資料庫中添加一個與已有表同名的表是不允許的。但你可以附加帶有與主資料庫中的表同名的表的資料庫。也可以多次附加同一資料庫。
使用database-name.table-name來引用附加資料庫中的表。若附加資料庫中的表與主資料庫的表不重名,則不需加資料庫名作為首碼。當資料庫被附加時,它的所有不重名的表成為該名字指向的預設表。之後附加的任意與之同名的表需要加首碼。若“預設”表被拆分,則最後附加的同名錶變為“預設”表。
若主資料庫不是“:memory:”,多附加資料庫的事務是原子的。若主資料庫是“:memory:”則事務在每個獨立文件中依然是原子的。但若主機在改變兩個或更多資料庫的COMMIT語句進行時崩潰,則可能一部分文件被改變而其他的保持原樣。附加資料庫的原子性的提交 是SQLite 3.0的新特性。在SQLite 2.8中,所有附加資料庫的提交類似於主資料庫是“:memory:”時的情況。
對附加資料庫的數目有編譯時的限制,最多10個附加資料庫。
BEGIN TRANSACTION
sql-statement ::= | BEGIN [ DEFERRED | IMMEDIATE | EXCLUSIVE ] [TRANSACTION [name]] |
sql-statement ::= | END [TRANSACTION [name]] |
sql-statement ::= | COMMIT [TRANSACTION [name]] |
sql-statement ::= | ROLLBACK [TRANSACTION [name]] |
從2.0版開始,SQLite支持帶有回退和原子性的提交的事務處理。
可選的事務名稱會被忽略。SQLite目前不允許嵌套事務。
在事務之外,不能對資料庫進行更改。如果當前沒有有效的事務,任何修改資料庫的命令(基本上除了SELECT以外的所有SQL命令)會自動啟動一個事務。命令結束時,自動啟動的事務會被提交。
可以使用BEGIN命令手動啟動事務。這樣啟動的事務會在下一條COMMIT或ROLLBACK命令之前一直有效。但若資料庫關閉或出現錯誤且選用ROLLBACK衝突判定演算法時,資料庫也會ROLLBACK。查看ON CONFLICT子句獲取更多關於ROLLBACK衝突判定演算法的信息。
在SQLite 3.0.8或更高版本中,事務可以是延遲的,即時的或者獨占的。“延遲的”即是說在資料庫第一次被訪問之前不獲得鎖。這樣就會延遲事務,BEGIN語句本身不做任何事情。直到初次讀取或訪問資料庫時才獲取鎖。對資料庫的初次讀取創建一個SHARED鎖 ,初次寫入創建一個RESERVED鎖。由於鎖的獲取被延遲到第一次需要時,別的線程或進程可以在當前線程執行BEGIN語句之後創建另外的事務 寫入資料庫。若事務是即時的,則執行BEGIN命令後立即獲取RESERVED鎖,而不等資料庫被使用。在執行BEGIN IMMEDIATE之後,你可以確保其它的線程或進程不能寫入資料庫或執行BEGIN IMMEDIATE或BEGIN EXCLUSIVE,但其它進程可以讀取資料庫。獨占事務在所有的資料庫獲取EXCLUSIVE鎖,在執行BEGIN EXCLUSIVE之後,你可以確保在當前事務結束前沒有任何其它線程或進程 能夠讀寫資料庫。
有關SHARED、RESERVED和EXCLUSIVE鎖可以參見這裡。
SQLite 3.0.8的預設行為是創建延遲事務。SQLite 3.0.0到3.0.7中延遲事務是唯一可用的事務類型。SQLite 2.8或更早版本中,所有的事務都是獨占的。
COMMIT命令在所有SQL命令完成之前並不作實際的提交工作。這樣若兩個或更多個SELECT語句在進程中間而執行COMMIT時,只有全部SELECT語句結束才進行提交。
執行COMMIT可能會返回SQLITE_BUSY錯誤代碼。這就是說有另外一個線程或進程獲取了資料庫的讀取鎖,並阻止資料庫被改變。當COMMIT獲得該錯誤代碼時,事務依然是活動的,並且在COMMIT可以在當前讀取的線程讀取結束後再次試圖讀取資料庫。
END TRANSACTION
sql-statement ::= | BEGIN [ DEFERRED | IMMEDIATE | EXCLUSIVE ] [TRANSACTION [name]] |
sql-statement ::= | END [TRANSACTION [name]] |
sql-statement ::= | COMMIT [TRANSACTION [name]] |
sql-statement ::= | ROLLBACK [TRANSACTION [name]] |
從2.0版開始,SQLite支持帶有回退和原子性的提交的事務處理。
可選的事務名稱會被忽略。SQLite目前不允許嵌套事務。
在事務之外,不能對資料庫進行更改。如果當前沒有有效的事務,任何修改資料庫的命令(基本上除了SELECT以外的所有SQL命令)會自動啟動一個事務。命令結束時,自動啟動的事務會被提交。
可以使用BEGIN命令手動啟動事務。這樣啟動的事務會在下一條COMMIT或ROLLBACK命令之前一直有效。但若資料庫關閉或出現錯誤且選用ROLLBACK衝突判定演算法時,資料庫也會ROLLBACK。查看ON CONFLICT子句獲取更多關於ROLLBACK衝突判定演算法的信息。
在SQLite 3.0.8或更高版本中,事務可以是延遲的,即時的或者獨占的。“延遲的”即是說在資料庫第一次被訪問之前不獲得鎖。這樣就會延遲事務,BEGIN語句本身不做任何事情。直到初次讀取或訪問資料庫時才獲取鎖。對資料庫的初次讀取創建一個SHARED鎖,初次寫入創建一個RESERVED鎖。由於鎖的獲取被延遲到第一次需要時,別的線程或進程可以在當前線程執行BEGIN語句之後創建另外的事務寫入資料庫。若事務是即時的,則執行BEGIN命令後立即獲取RESERVED鎖,而不等資料庫被使用。在執行BEGIN IMMEDIATE之後,你可以確保其它的線程或進程不能寫入資料庫或執行BEGIN IMMEDIATE或BEGIN EXCLUSIVE,但其它進程可以讀取資料庫。獨占事務在所有的資料庫獲取EXCLUSIVE鎖,在執行BEGIN EXCLUSIVE之後,你可以確保在當前事務結束前沒有任何其它線程或進程能夠讀寫資料庫。
有關SHARED、RESERVED和EXCLUSIVE鎖可以參見這裡。
SQLite 3.0.8的預設行為是創建延遲事務。SQLite 3.0.0到3.0.7中延遲事務是唯一可用的事務類型。SQLite 2.8或更早版本中,所有的事務都是獨占的。
COMMIT命令在所有SQL命令完成之前並不作實際的提交工作。這樣若兩個或更多個SELECT語句在進程中間而執行COMMIT時,只有全部SELECT語句結束才進行提交。
執行COMMIT可能會返回SQLITE_BUSY錯誤代碼。這就是說有另外一個線程或進程獲取了資料庫的讀取鎖,並阻止資料庫被改變。當COMMIT獲得該錯誤代碼時,事務依然是活動的,並且在COMMIT可以在當前讀取的線程讀取結束後再次試圖讀取資料庫。
註釋
comment ::= | SQL-comment | C-comment |
SQL-comment ::= | -- single-line |
C-comment ::= | /* multiple-lines [*/] |
註釋不是SQL命令,但會出現在SQL查詢中。它們被解釋器處理為空白部分。它們可以在任何空白可能存在的地方開始 ,即使是在跨越多行的表達式中。
SQL風格的註釋僅對當前行有效。
C風格的註釋可以跨越多行。若沒有結束符號,註釋的範圍將一直延伸到輸入末尾,且不會引起報錯。新的SQL語句可以從多行註釋結束的地方開始。C風格註釋可以嵌入任何空白可以出現的地方,包括表達式內,或其他SQL語句中間, 並且C風格的註釋不互相嵌套。SQL風格的註釋出現在C風格註釋中時將被忽略。
COPY
sql-statement::= | COPY [ OR conflict-algorithm ] [database-name .] table-name FROMfilename [ USING DELIMITERS delim ] |
COPY命令在SQLite 2.8及更早的版本中可用。SQLite 3.0刪除了這一命令,因為在混合的UTF-8/16環境中對它進行支持是很複雜的。在3.0版本中,命令行解釋器包含新的.import命令,用以替代COPY。
COPY命令是用於將大量數據插入表的一個插件。它模仿PostgreSQL中的相同命令而來。事實上,SQLite的COPY 命令就是為了能夠讀取PostgreSQL的備份工具pg_dump的輸出從而能夠將PostgreSQL的數據輕鬆轉換到SQLite中而設計的。
table-name是將要導入數據的一個已存在的表的名字。filename是一個字元串或標識符,用於說明作為數據來源的文件。filename可以使用STDIN從標準輸入流中獲取數據。
輸入文件的每一行被轉換成一條單獨的記錄導入表中。欄位用製表符分開。若某個欄位的數據中出現製表符,則前面被添加反斜線“/”符號。數據中的反斜線則被替換為兩條反斜線。可選的USING DELIMITERS子句可給出一個與製表符不同 的分界符。
若欄位由“/N”組成,則被賦以空值NULL。
使用這一命令時,利用可選的ON CONFLICT子句可以定義替代的約束衝突判定演算法。更多信息,參見 ON CONFLICT。
當輸入數據源是STDIN,輸入將終止於一行僅包含一個反斜線和一個點的輸入:“/.”。
CREATE INDEX
sql-statement ::= | CREATE [UNIQUE] INDEX [IF NOT EXISTS] [database-name .] index-name ON table-name ( column-name [, column-name]* ) |
column-name ::= | name [ COLLATE collation-name] [ ASC | DESC ] |
CREATE INDEX命令由“CREATE INDEX”關鍵字後跟新索引的名字,關鍵字“ON”,待索引表的名字,以及括弧內的用於索引鍵的欄位列表構成。每個欄位名可以跟隨“ASC”或“DESC”關鍵字說明排序法則,但在當前版本中排序法則被忽略。排序總是按照上升序。
每個欄位名後跟COLLATE子句定義文本記錄的比較順序。預設的比較順序是由CREATE TABLE語句說明的比較順序。若不定義比較順序,則使用內建的二進位比較順序。
附加到單個表上的索引數目沒有限制,索引中的欄位數也沒有限制。
若UNIQUE關鍵字出現在CREATE和INDEX之間,則不允許重名的索引記錄。試圖插入重名記錄將會導致錯誤。
每條CREATE INDEX語句的文本儲存於sqlite_master或sqlite_temp_master表中,取決於被索引的表是否臨時表。 每次打開資料庫時,所有的CREATE INDEX語句從sqlite_master表中讀出,產生SQLite的索引樣式的內部結構。
若使用可選的IF NOT EXISTS子句,且存在同名索引,則該命令無效。
使用DROP INDEX命令刪除索引。
CREATE TABLE
sql-command ::= | CREATE [TEMP | TEMPORARY] TABLE [IF NOT EXISTS] table-name ( column-def [, column-def]* [, constraint]* ) |
sql-command ::= | CREATE [TEMP | TEMPORARY] TABLE [database-name.] table-name ASselect-statement |
column-def ::= | name [type] [[CONSTRAINT name] column-constraint]* |
type ::= | typename | typename ( number ) | typename ( number , number ) |
column-constraint ::= | NOT NULL [ conflict-clause ] | PRIMARY KEY [sort-order] [ conflict-clause ] [AUTOINCREMENT] | UNIQUE [ conflict-clause ] | CHECK ( expr ) | DEFAULT value | COLLATE collation-name |
constraint ::= | PRIMARY KEY ( column-list ) [ conflict-clause ] | UNIQUE ( column-list ) [ conflict-clause ] | CHECK ( expr ) |
conflict-clause::= | ON CONFLICT conflict-algorithm |
CREATE TABLE語句基本上就是“CREATE TABLE”關鍵字後跟一個新的表名以及括弧內的一堆定義和約束。表名可以是字元串或者標識符。以“sqlite_”開頭的表名是留給資料庫引擎使用的。
每個欄位的定義是欄位名後跟欄位的數據類型,接著是一個或多個的欄位約束。欄位的數據類型並不限制欄位中可以存放的數據。可以查看SQLite3的數據類型獲取更多信息。UNIQUE約束為指定的欄位創建索引,該索引須含有唯一鍵。COLLATE子句說明在比較欄位的 文字記錄時所使用的排序函數。預設使用內嵌的BINARY排序函數。
DEFAULT約束說明在使用INSERT插入欄位時所使用的預設值。該值可以是NULL,字元串常量或一個數。從3.1.0版開始,預設值也可以是以下特殊的與事件無關的關鍵字CURRENT_TIME、CURRENT_DATE或CURRENT_TIMESTAMP。若預設值為NULL、字元串常量或數,在執行未指明欄位值的INSERT語句的時候它被插入欄位。若預設值是CURRENT_TIME、CURRENT_DATE或CURRENT_TIMESTAMP,則當前UTC日期和/或時間被插入欄位。CURRENT_TIME的格式為“HH:MM:SS”,CURRENT_DATE為“YYYY-MM-DD”,而CURRENT_TIMESTAMP是“YYYY-MM-DD HH:MM:SS”。
正常情況下定義PRIMARY KEY只是在相應欄位上創建一個UNIQUE索引。然而,若主鍵定義在單一的INTEGER類型的欄位上,則該欄位在內部被用作表的B-Tree鍵。這即是說欄位僅能容納唯一整數值。(在除此之外的其它情況下,SQLite忽略數據類型的說明 ,允許任何類型的數據放入欄位中,不管該欄位被聲明為什麼數據類型。)若一個表中不含一個INTEGER PRIMARY KEY欄位,則B-Tree鍵為自動產生的整數。一行的B-Tree鍵可以通過如下特殊的名字“ROWID”、“OID”或“_ROWID_”進行訪問,不論是否有INTEGER PRIMARY KEY存在。INTEGER PRIMARY KEY欄位可以使用關鍵字AUTOINCREMENT聲明。AUTOINCREMENT關鍵字修改了B-Tree鍵自動產生的方式。B-Tree鍵的生成的其它信息可以在這裡找到。
若“TEMP”或“TEMPORARY”關鍵字出現在“CREATE”和“TABLE”之間,則所建立的表僅在當前資料庫連接可見,併在斷開連接時自動被刪除。在臨時表上建立的任何索引也是臨時的。臨時表和索引單獨存儲在與主資料庫文件不同的文件中。
若說明瞭,則表在該資料庫中被創建。同時聲明和TEMP關鍵字會出錯,除非 是“temp”。若不聲明資料庫名,也不使用TEMP關鍵字,則表創建於主資料庫中。
在每個約束後跟可選的ON CONFLICT子句可以定義替代的約束衝突判定演算法。 預設為ABORT。同一個表中的不同約束可以使用不同的預設衝突判定演算法。若一條COPY、INSERT或UPDATE命令指定了不同的衝突判定演算法,則該演算法將替代CREATE TABLE語句中說明的預設演算法。更多信息,參見ON CONFLICT。
3.3.0版支持CHECK約束。在3.3.0之前,CHECK約束被解析但不執行。
表中的欄位數或約束數沒有任何限制。在2.8版中,單行數據的總數被限製為小於1 megabytes。而在3.0中則消除了限制。
CREATE TABLE AS形式定義表為一個查詢的結果集。表的欄位名字即是結果中的欄位名字。
每條CREATE TABLE語句的文本都儲存在sqlite_master表中。每當資料庫被打開,所有的CREATE TABLE語句從 sqlite_master表中讀出,構成表結構的SQLite內部實現。若原始命令為CREATE TABLE AS則合成出等效的CREATE TABLE語句並儲存於sqlite_master表中代替原命令。CREATE TEMPORARY TABLE語句文本儲存於sqlite_temp_master表中。
若在命令中使用可選的IF NOT EXISTS子句且存在同名的另一個表,則當前的命令無效。
刪除表可以使用DROP TABLE語句。
CREATE TRIGGER
sql-statement ::= | CREATE [TEMP | TEMPORARY] TRIGGER trigger-name [ BEFORE | AFTER ] database-event ON [database-name .] table-name trigger-action |
sql-statement ::= | CREATE [TEMP | TEMPORARY] TRIGGER trigger-name INSTEAD OF database-event ON [database-name .] view-name trigger-action |
database-event ::= | DELETE | INSERT | UPDATE | UPDATE OF column-list |
trigger-action ::= | [ FOR EACH ROW | FOR EACH STATEMENT ] [ WHEN expression ] BEGIN trigger-step ; [ trigger-step ; ]* END |
trigger-step ::= | update-statement | insert-statement | delete-statement | select-statement |
CREATE TRIGGER語句用於向資料庫schema中添加觸發器。觸發器是一些在特定的資料庫事件(database-event)發生時自動進行的資料庫操作(trigger-action)。
觸發器可由在特殊表上執行的DELETE、INSERT、UPDATE等語句觸發,或UPDATE表中特定的欄位時觸發。
現在SQLite僅支持FOR EACH ROW觸發器,不支持FOR EACH STATEMENT觸發。因此可以不用明確說明FOR EACH ROW。FOR EACH ROW的意思是由trigger-steps說明的SQL語句可能在(由WHEN子句決定的)資料庫插入,更改或刪除的每一行觸發trigger。
WHEN子句和trigger-steps可以使用“NEW.column-name”和“OLD.column-name”的引用形式訪問正在被插入,更改或刪除的行的元素,column-name是觸發器關聯的表中的欄位名。OLD和NEW引用只在觸發器與之相關的trigger-event處可用,例如:
INSERT | NEW可用 |
UPDATE | NEW和OLD均可用 |
DELETE | OLD可用 |
當使用WHEN子句,trigger-steps只在WHEN子句為真的行執行。不使用WHEN時則在所有行執行。
trigger-time決定了trigger-steps執行的時間,它是相對於關聯行的插入、刪除和修改而言的。
作為的一部分trigger-step的UPDATE或INSERT可以使用ON CONFLICT子句。但若觸發trigger的語句使用了ON CONFLICT子句,則覆蓋前述的ON CONFLICT子句所定義的衝突處理方法。
關聯表被撤銷時觸發器被自動刪除。
不僅在表上,在視圖上一樣可以創建觸發器,在CREATE TRIGGER語句中使用INSTEAD OF即可。若視圖上定義了一個或多個ON INSERT、ON DELETE、ON UPDATE觸發器,則相應地對視圖執行INSERT、DELETE或UPDATE語句不會出錯,而會觸發關聯的觸發器。視圖關聯的表不會被修改。(除了由觸發器進行的修改操作)。
例子:
假設“customers”表存儲了客戶信息,“orders”表存儲了訂單信息,下麵的觸發器確保當用戶改變地址時所有的關聯訂單地址均進行相應改變:
CREATE TRIGGER update_customer_address UPDATE OF address ON customers BEGIN UPDATE orders SET address = new.address WHERE customer_name = old.name; END;
定義了該觸發器後執行如下語句:
UPDATE customers SET address = ’1 Main St.’ WHERE name = ’Jack Jones’;
會使下麵的語句自動執行:
UPDATE orders SET address = ’1 Main St.’ WHERE customer_name = ’Jack Jones’;
註意,目前在有INTEGER PRIMARY KEY域的表上觸發器可能工作不正常。若BEFORE觸發器修改了一行的INTEGER PRIMARY KEY域,而該域將由觸發該觸發器的語句進行修改,則可能根本不會修改該域。可以用PRIMARY KEY欄位代替INTEGER PRIMARY KEY欄位來解決上述問題。
一個特殊的SQL函數RAISE()可用於觸發器程式,使用如下語法:
raise-function ::= | RAISE ( ABORT, error-message ) | RAISE ( FAIL, error-message ) | RAISE ( ROLLBACK, error-message ) | RAISE ( IGNORE ) |
當觸發器程式執行中調用了上述前三個之一的形式時,則執行指定的ON CONFLICT進程(ABORT、FAIL或者ROLLBACK)且終止當前查詢,返回一個SQLITE_CONSTRAINT錯誤並說明錯誤信息。
當調用RAISE(IGNORE),當前觸發器程式的餘下部分,觸發該觸發器的語句和任何之後的觸發器程式被忽略並且不恢復對資料庫的已有改變。若觸發觸發器的語句是一個觸發器程式本身的一部分,則原觸發器程式從下一步起繼續執行。
使用DROP TRIGGER刪除觸發器。
CREATE VIEW
sql-command::= | CREATE [TEMP | TEMPORARY] VIEW [database-name.] view-name ASselect-statement |
CREATE VIEW命令為一個包裝好的SELECT語句命名。當創建了一個視圖,它可以用於其他SELECT的FROM字句中代替表名。
若“TEMP”或“TEMPORARY”關鍵字出現在“CREATE”和“VIEW”之間,則創建的視圖僅對打開資料庫的進程可見,且在資料庫關閉時自動刪除。
若指定了則視圖在指定的資料庫中創建。同時使用和TEMP關鍵字會導致錯誤,除非是“temp”。若不聲明資料庫名,也不使用TEMP關鍵字,則視圖創建於主資料庫中。
你不能對視圖使用COPY、DELETE、INSERT或UPDATE,視圖在SQLite中是只讀的。多數情況下你可以在視圖上創建TRIGGER來達到相同目的。用DROP VIEW命令來刪除視圖。
DELETE
sql-statement ::= | DELETE FROM [database-name .] table-name [WHERE expr] |
DELETE命令用於從表中刪除記錄。命令包含“DELETE FROM”關鍵字以及需要刪除的記錄所在的表名。
若不使用WHERE子句,表中的所有行將全部被刪除。否則僅刪除符合條件的行。
DETACH DATABASE
sql-command ::= | DETACH [DATABASE] database-name |
該語句拆分一個之前使用ATTACH DATABASE語句附加的資料庫連接。可以使用不同的名字多次附加同一資料庫,並且拆分一個連接不會影響其他連接。
若SQLite在事務進行中,該語句不起作用。
DROP INDEX
sql-command ::= | DROP INDEX [IF EXISTS] [database-name .] index-name |
DROP INDEX語句刪除由CREATE INDEX語句創建的索引。索引將從資料庫結構和磁碟文件中完全刪除,唯一的恢復方法是重新輸入相應的CREATE INDEX命令。
DROP TABLE語句在預設模式下不減小資料庫文件的大小。空間會留給後來的INSERT語句使用。要釋放刪除產生的空間,可以使用VACUUM命令。若AUTOVACUUM模式開啟,則空間會自動被DROP INDEX釋放。
DROP TABLE
sql-command ::= | DROP TABLE [IF EXISTS] [database-name.] table-name |
DROP TABLE語句刪除由CREATE TABLE語句創建的表。表將從資料庫結構和磁碟文件中完全刪除,且不能恢復。該表的所有索引也同時被刪除。
DROP TABLE語句在預設模式下不減小資料庫文件的大小。空間會留給後來的INSERT語句使用。要釋放刪除產生的空間,可以使用VACUUM命令。若AUTOVACUUM模式開啟,則空間會自動被DROP TABLE釋放。
若使用可選的IF EXISTS子句,在刪除的表不存在時就不會報錯。
DROP TRIGGER
sql-statement ::= | DROP TRIGGER [database-name .] trigger-name |
DROP TRIGGER語句刪除由CREATE TRIGGER創建的觸發器。觸發器從資料庫的schema中刪除。註意當關聯的表被撤消時觸發器自動被刪除。
DROP VIEW
sql-command ::= | DROP VIEW view-name |
DROP VIEW語句刪除由CREATE VIEW創建的視圖。視圖從資料庫的schema中刪除,表中的數據不會被更改。
EXPLAIN
sql-statement ::= | EXPLAIN sql-statement |
EXPLAIN命令修飾語是一個非標準的擴展功能,靈感來自PostgreSQL中的相同命令,但操作完全不同。
若EXPLAIN關鍵字出現在任何SQLite的SQL命令之前,則SQLite庫返回不加EXPLAIN時執行該命令所需要使用的虛擬機指令序列,而不是真正執行該命令。關於虛擬機指令的更多信息參見系統結構描述或關於虛擬機的可用代碼。
表達式
expr ::= | expr binary-op expr | expr [NOT] like-op expr [ESCAPE expr] | unary-op expr | ( expr ) | column-name | table-name . column-name | database-name . table-name . column-name | literal-value | parameter | function-name ( expr-list | * ) | expr ISNULL | expr NOTNULL | expr [NOT] BETWEEN expr AND expr | expr [NOT] IN ( value-list ) | expr [NOT] IN ( select-statement ) | expr [NOT] IN [database-name .] table-name | [EXISTS] ( select-statement ) | CASE [expr] ( WHEN expr THEN expr )+ [ELSE expr] END | CAST ( expr AS type ) |
like-op ::= | LIKE | GLOB | REGEXP |
這一節與其它的各節有所不同。我們討論的不是一個單一的SQL命令,而是作為其他大部分命令的一部分的表達式。
SQLite支持如下的二元運算符,按優先順序由高至低排列:
|| * / % + - << >> & | < <= > >= = == != <>IN AND OR
所支持的一元運算符:
- + ! ~
註意等號和“不等”號的兩個變種。等號可以是 =或==. “不等”號可以是!=或<>. ||為“連接符”——它將兩個字元串連接起來。 %輸出左邊部分以右邊部分為模取模得到的餘數。
二元運算符的結果均為數字,除了||連接符,它給出字元串結果。
文本值(literal value)是一個整數或浮點數。可以使用科學計數法。“.”符號總是被當作小數點即使本地設定中用“,”來表示小數點——用“,”表示小數點會造成歧義。字元串常量由字元串加單引號“'”構成。字元串內部的單引號可像Pascal中一樣用兩個單引號來表示。C風格的加反斜線的表示法由於不是標準SQL而不被支持。BLOB文本是以“x”或“X”開頭的含有十六進位文本信息的文本值。例如:
X'53514697465'
文本值同樣可以為“NULL”。
表達式中插入文本值占位符的參數可以使用sqlite3_bind API函數在運行時插入。參數可以是如下幾種形式:
?NNN 問號跟隨數字NNN為第NNN個參數占位。NNN需介於1和999之間。 ? 不加數字的問號為下一個參數占位。 :AAAA 冒號帶一個標識符名稱為一個名為AAAA的參數占位。命名的參數同樣可以使用序號占位,被賦予的參數序號為下一個尚未被使用的序號。建議不要混合使用命名代表的參數和序號代表的參數以免引起混淆。 $AAAA $符號帶一個標識符名稱也可以為一個名為AAAA的參數占位。在這一情況下標識符名稱可以包括一個或更多的“::”以及包含任何文本的“(...)”尾碼。該語法是Tcl編程語言中的一個可變形式。
不使用sqlite3_bind賦值的參數被視為NULL。
LIKE運算符進行模式匹配比較。運算符右邊為進行匹配的模式而左邊為需進行匹配的字元串。模式中的百分號%匹配結果中的零或任意多個字元。下劃線_匹配任意單個字元。其他的任意字元匹配本身或等同的大/小寫字元。(即不區分大小寫的匹配)。(一個bug:SQLite僅對7-bit拉丁字元支持不區分大小寫匹配。這是由於LIKE運算符對8-bit ISO8859字元或UTF-8字元是大小寫敏感的。例如,表達式'a' LIKE 'A'的值為真而'æ' LIKE 'Æ'為假)。
如果使用可選的ESCAPE子句,則跟隨ESCAPE關鍵字的必須是一個有一個字元的字元串。這一字元(逃逸字元)可用於LIKE模式中,以代替百分號或下劃線。逃逸字元後跟百分號,下劃線或它本身代表字元串中的百分號,下劃線或逃逸字元。插入的LIKE運算符功能通過調用用戶函數like(X,Y)來實現。
當使用可選的ESCAPE子句,它對函數給出第三個參數,LIKE的功能可以通過重載SQL函數like()進行改變。
GLOB運算符與LIKE相似,但它使用Unix文件globbing語法作為通配符。還有一點不同是GLOB對大小寫敏感。GLOB和LIKE都可以首碼NOT關鍵字構成相反的意思。插入的GLOB運算符功能通過調用用戶函數glob(X,Y)可以通過重載函數改變GLOB的功能。
REGEXP運算符是用戶函數regexp()的一個特殊的代表符號。預設情況下regexp()函數不被定義,所以使用REGEXP運算符會報錯。當運行時存在用戶定義的“regexp”函數的定義,則調用該函數以實現REGEXP運算符功能。
欄位名可以是CREATE TABLE語句定義的任何名字或如下幾個特殊標識符之一“ROWID”、“OID”以及“_ROWID_”。這些特殊標識符均代表每個表每一行關聯的那個唯一隨機整數鍵“row key”。僅僅在CREATE TABLE語句沒有對這些特殊標識符的真實欄位予以定義的情況下,它們才代表“row key”。它們與只讀欄位類似,可以像任何正常欄位一樣使用,除了在UPDATE或INSERT語句中(即是說你不能添加或更改row key)。“SELECT * ...”不返回row key。
SELECT語句可以在表達式中出現,作為IN運算符的右邊運算量,作為一個純量,或作為EXISTS運算符的運算量。當作純量或IN的運算量時,SELECT語句的結果僅允許有一個欄位,可以使用複合的SELECT(用UNION或 EXCEPT等關鍵字連接)。作為EXISTS運算符的運算量時,SELECT結果中的欄位被忽略,在結果為空時表達式為假,反之為真。若SELECT表達式代表的查詢中不含有引用值的部分,則它將在處理其它事務之前被計算,並且結果在必要時會被重覆使用。若SELECT表達式含從其它查詢中得到的變數,在每一次使用時該表達式均被重新計算。
當SELECT作為IN運算符的右運算量,在左邊的運算量是SELECT產生的任意一個值時,表達式返回TRUE。IN運算符前可以加NOT構成相反的意思。
當SELECT與表達式一同出現且不在IN的右邊,則SELECT結果的第一行作為表達式中使用的值。SELECT返回的結果在第一行以後的部分被忽略。返回結果為空時SELECT語句的值為NULL。
CAST表達式將的數據類型改為聲明的類型。可以是CREATE TABLE語句欄位定義部分定義的對該欄位有效的任意非空數據類型。
表達式支持簡單函數和聚集函數。簡單函數直接從輸入獲得結果,可用於任何表達式中。聚集函數使用結果集中的所有行計算結果,僅用於SELECT語句中。
T下麵這些函數是預設可用的。可以使用C語言寫出其它的函數然後使用sqlite3_create_function()API函數添加到資料庫引擎中。
abs(X) | 返回參數X的絕對值。 |
coalesce(X,Y,...) | 返回第一個非空參數的副本。若所有的參數均為NULL,返回NULL。至少2個參數。 |
glob(X,Y) | 用於實現SQLite的 "X GLOB Y"語法。可使用 sqlite3_create_function() 重載該函數從而改變GLOB運算符的功能。 |
ifnull(X,Y) | 返回第一個非空參數的副本。 若兩個參數均為NULL,返回NULL。與上面的 coalesce()類似。 |
last_insert_rowid() | 返回當前資料庫連接最後插入行的ROWID。sqlite_last_insert_rowid()API函數同樣可用於得到該值。 |
length(X) | 返回X的長度,以字元計。如果SQLite被配置為支持UTF-8,則返回UTF-8字元數而不是位元組數。 |
like(X,Y [,Z]) | 用於實現SQL語法"X LIKE Y [ESCAPE Z]".若使用可選的ESCAPE子句,則函數被賦予三個參數,否則只有兩個。可使用sqlite3_create_function() 重載該函數從而改變LIKE運算符的功能。 |
lower(X) | 返回X字元串的所有字元小寫化版本。這一轉換使用C語言庫的tolower()函數,對UTF-8字元不能提供好的支持。 |
max(X,Y,...) | 返回最大值。參數可以不僅僅為數字,可以為字元串。大小順序由常用的排序法則決定。註意,max()在有2個或更多參數時為簡單函數,但當僅給出一個參數時它變為聚集函數。 |
min(X,Y,...) | 返回最小值。與max()類似。 |
nullif(X,Y) | 當兩參數不同時返回X,否則返回NULL. |
quote(X) | 返回參數的適於插入其它SQL語句中的值。字元串會被添加單引號,在內部的引號前會加入逃逸符號。 BLOB被編碼為十六進位文本。當前的VACUUM使用這一函數實現。在使用觸發器實現撤銷/重做功能時這一函數也很有用。 |
random(*) | 返回介於-2147483648和 +2147483647之間的隨機整數。 |
round(X) round(X,Y) |
將X四捨五入,保留小數點後Y位。若忽略Y參數,則預設其為0。 |
soundex(X) | 計算字元串X的soundex編碼。參數為NULL時返回字元串“?000”。預設的SQLite是不支持該函數的,當編譯時選項 -DSQLITE_SOUNDEX=1 時該函數才可用。 |
sqlite_version(*) | 返回所運行的SQLite庫的版本號字元串。如 "2.8.0"。 |
substr(X,Y,Z) | 返回輸入字元串X中以第Y個字元開始,Z個字元長的子串。X最左端的字元序號為1。若Y為負,則從右至左數起。若SQLite配置支持UTF-8,則“字元”代表的是UTF-8字元而非位元組。 |
typeof(X) | 返回表達式X的類型。返回值可能為“null”、“integer”、“real”、“text”以及“blob”。SQLite的類型處理參見SQLite3的數據類型。 |
upper(X) | 返回X字元串的所有字元大寫化版本。這一轉換使用C語言庫的toupper()函數,對UTF-8字元不能提供好的支持。 |
以下是預設可用的聚集函數列表。可以使用C語言寫出其它的聚集函數然後使用sqlite3_create_function() API函數添加到資料庫引擎中。
在單參數聚集函數中,參數可以加首碼DISTINCT。這時重覆參數會被過濾掉,然後才穿入到函數中。例如,函數“count(distinct X)”返回欄位X的不重覆非空值的個數,而不是欄位X的全部非空值。
avg(X) | 返回一組中非空的X的平均值。非數字值作0處理。avg()的結果總是一個浮點數,即使所有的輸入變數都是整數。
|
count(X) count(*) |
返回一組中X是非空值的次數的第一種形式。第二種形式(不帶參數)返回該組中的行數。 |
max(X) | 返回一組中的最大值。大小由常用排序法決定。 |
min(X) | 返回一組中最小的非空值。大小由常用排序法決定。僅在所有值為空時返回NULL。 |
sum(X) total(X) |
返回一組中所有非空值的數字和。若沒有非空行,sum()返回NULL而total()返回0.0。NULL通常情況下並不是對於“沒有行”的和的一個有意義的結果,但SQL標準如此要求,且大部分其它SQL資料庫引擎這樣定義sum(),所以SQLite 也如此定義以保證相容。我們提供非標準的total()函數作為解決該SQL語言設計問題的一個簡易方法。
total()的返回值式中為浮點數。sum()可以為整數,當所有非空輸入均為整數時,和是精確的。若sum()的任意一個輸入既非整數也非NULL或計算中產生整數類型的溢出時,sum()返回接近真和的浮點數。 |
INSERT