菜鳥入門
1。從www.sqlite .org 下載SQLite 3.3.4的版本
為了方便,我把它解壓了,就一個SQLite3.exe,放入Windows目錄下。
Cmd 進(jìn)入命令行
1)
創(chuàng)建數(shù)據(jù)庫文件:
>SQLite3 d:\test.db 回車
就生成了一個test.db在d盤。
這樣同時也SQLite3掛上了這個test.db
2)
用.help可以看看有什么命令
>.help 回車即可
3)可以在這里直接輸入SQL語句創(chuàng)建表格 用;結(jié)束 ,然后回車就可以看到了
4)看看有創(chuàng)建了多少表
>.tables
5)看表結(jié)構(gòu)
>.schema 表名
6)看看目前的數(shù)據(jù)庫
>.database
7)如果要把查詢輸出到文件
>.output 文件名
> 查詢語句;
查詢結(jié)果就輸出到了文件c:\query.txt
把查詢結(jié)果用屏幕輸出
>.output stdout
8)把表結(jié)構(gòu)輸出,同時索引也會輸出
.dump 表名
9)退出
>.exit 或者.quit
2。從http://sqlite .phxsoftware.com/ 下載Ado.net驅(qū)動。
下載了安裝,在安裝目錄中存在System.Data.SQLite .dll
我們只需要拷貝這個文件到引用目錄,并添加引用即可對SQLite 數(shù)據(jù)庫操作了
所有的Ado.net對象都是以SQLite 開頭的,比如SQLiteConnection
連接串只需要如下方式
Data Source=d:\test.db 或者DataSource=test.db--應(yīng)用在和應(yīng)用程序或者.net能夠自動找到的目錄
剩下的就很簡單了~~
3。SQL語法
由于以前用SQLServer或者ISeries,所以DDL的語法很汗顏
1)創(chuàng)建一個單個Primary Key的table
CREATE TABLE [Admin] (
[UserName] [nvarchar] (20) PRIMARY KEY NOT NULL ,
[Password] [nvarchar] (50) NOT NULL ,
[Rank] [smallint] NOT NULL ,
[MailServer] [nvarchar] (50) NOT NULL ,
[MailUser] [nvarchar] (50) NOT NULL ,
[MailPassword] [nvarchar] (50) NOT NULL ,
[Mail] [nvarchar] (50) NOT NULL
) ;
2)創(chuàng)建一個多個Primary Key的table
CREATE TABLE [CodeDetail] (
[CdType] [nvarchar] (10) NOT NULL ,
[CdCode] [nvarchar] (20) NOT NULL ,
[CdString1] [ntext] NOT NULL ,
[CdString2] [ntext] NOT NULL ,
[CdString3] [ntext] NOT NULL,
PRIMARY KEY (CdType,CdCode)
) ;
3)創(chuàng)建索引
CREATE INDEX [IX_Account] ON [Account]([IsCheck], [UserName]);
還可以視圖等等。
4.還有很有用的SQL
Select * from Sqlite_master
Select datetime('now')
Select date('now')
Select time('now')
SQLite 內(nèi)建函數(shù)表
算術(shù)函數(shù)
|
abs(X)
|
返回給定數(shù)字表達(dá)式的絕對值。
|
max(X,Y[,...])
|
返回表達(dá)式的最大值。
|
min(X,Y[,...])
|
返回表達(dá)式的最小值。
|
random(*)
|
返回隨機(jī)數(shù)。
|
round(X[,Y])
|
返回數(shù)字表達(dá)式并四舍五入為指定的長度或精度。
|
字符處理函數(shù)
|
length(X)
|
返回給定字符串表達(dá)式的字符個數(shù)。
|
lower(X)
|
將大寫字符數(shù)據(jù)轉(zhuǎn)換為小寫字符數(shù)據(jù)后返回字符表達(dá)式。
|
upper(X)
|
返回將小寫字符數(shù)據(jù)轉(zhuǎn)換為大寫的字符表達(dá)式。
|
substr(X,Y,Z)
|
返回表達(dá)式的一部分。
|
randstr()
|
|
quote(A)
|
|
like(A,B)
|
確定給定的字符串是否與指定的模式匹配。
|
glob(A,B)
|
|
條件判斷函數(shù)
|
coalesce(X,Y[,...])
|
|
ifnull(X,Y)
|
|
nullif(X,Y)
|
|
集合函數(shù)
|
avg(X)
|
返回組中值的平均值。
|
count(X)
|
返回組中項目的數(shù)量。
|
max(X)
|
返回組中值的最大值。
|
min(X)
|
返回組中值的最小值。
|
sum(X)
|
返回表達(dá)式中所有值的和。
|
其他函數(shù)
|
typeof(X)
|
返回數(shù)據(jù)的類型。
|
last_insert_rowid()
|
返回最后插入的數(shù)據(jù)的 ID 。
|
sqlite_version(*)
|
返回 SQLite 的版本。
|
change_count()
|
返回受上一語句影響的行數(shù)。
|
last_statement_change_count()
|
|
oh,還有就是看到有人說,好像成批插入的時候,啟動事務(wù),比不啟動事務(wù)快n倍
還有就是盡量使用參數(shù)化的SQL,估計和商用DB一樣能夠自動Prepare.
===========
sqlite 可以在shell/dos command底下直接執(zhí)行命令:
sqlite3 film.db "select * from film;"
輸出 HTML 表格:
sqlite3 -html film.db "select * from film;"
將數(shù)據(jù)庫「倒出來」:
sqlite3 film.db ".dump" > output.sql
利用輸出的資料,建立一個一模一樣的數(shù)據(jù)庫(加上以上指令,就是標(biāo)準(zhǔn)的SQL數(shù)據(jù)庫備份了):
sqlite3 film.db < output.sql
在大量插入資料時,你可能會需要先打這個指令:
begin;
插入完資料后要記得打這個指令,資料才會寫進(jìn)數(shù)據(jù)庫中:
commit;
SQLITE 深入------常見問題
如何建立自動增長字段?
簡短回答:聲明為 INTEGER PRIMARY KEY 的列將會自動增長 。
長一點的答案: 如果你聲明表的一列為 INTEGER PRIMARY
KEY,那么, 每當(dāng)你在該列上插入一NULL值時, NULL自動被轉(zhuǎn)換為一個比該列中最大值大1的一個整數(shù),如果表是空的, 將會是1。
(如果是最大可能的主鍵 9223372036854775807,那個,將鍵值將是隨機(jī)未使用的數(shù)。) 如,有下列表:
CREATE TABLE t1(
a INTEGER PRIMARY KEY,
b INTEGER
);
在該表上,下列語句
INSERT INTO t1 VALUES(NULL,123);
在邏輯上等價于:
INSERT INTO t1 VALUES((SELECT max(a) FROM t1)+1,123);
有一個新的API叫做 sqlite3_last_insert_rowid(), 它將返回最近插入的整數(shù)值。 注
意該整數(shù)會比表中該列上的插入之前的最大值大1。
該鍵值在當(dāng)前的表中是唯一的。但有可能與已從表中刪除的值重疊。要想建立在整個表的生命周期中唯一的鍵值,需要在 INTEGER PRIMARY
KEY
上增加AUTOINCREMENT聲明。那么,新的鍵值將會比該表中曾能存在過的最大值大1。如果最大可能的整數(shù)值在數(shù)據(jù)表中曾經(jīng)存在過,INSERT將
會失敗, 并返回SQLITE_FULL錯誤代碼。
多個應(yīng)用程序或一個應(yīng)用程序的多個實例可以同時訪問同一個數(shù)據(jù)庫文件嗎?
多個進(jìn)程可同時打開同一個數(shù)據(jù)庫。多個進(jìn)程可以同時進(jìn)行SELECT 操作,但在任一時刻,只能有一個進(jìn)程對數(shù)據(jù)庫進(jìn)行更改。
SQLite
使用讀、寫鎖控制對數(shù)據(jù)庫的訪問。(在Win95/98/ME等不支持讀、寫鎖的系統(tǒng)下,使用一個概率性的模擬來代替。)但使用時要注意:
如果數(shù)據(jù)庫文件存放于一個NFS文件系統(tǒng)上,這種鎖機(jī)制可能不能正常工作。 這是因為 fcntl() 文件鎖在很多NFS上沒有正確的實現(xiàn)。
在可能有多個進(jìn)程同時訪問數(shù)據(jù)庫的時候,應(yīng)該避免將數(shù)據(jù)庫文件放到NFS上。在Windows上,Microsoft的文檔中說:如果使用 FAT
文件系統(tǒng)而沒有運(yùn)行 share.exe
守護(hù)進(jìn)程,那么鎖可能是不能正常使用的。那些在Windows上有很多經(jīng)驗的人告訴我:對于網(wǎng)絡(luò)文件,文件鎖的實現(xiàn)有好多Bug,是靠不住的。如果他們說
的是對的, 那么在兩臺或多臺Windows機(jī)器間共享數(shù)據(jù)庫可能會引起不期望的問題。
我們意識到,沒有其它嵌入式的 SQL 數(shù)據(jù)庫引擎能象 SQLite 這樣處理如此多的并發(fā)。SQLite 允許多個進(jìn)程同時打開一個數(shù)據(jù)庫,同時讀一個數(shù)據(jù)庫。當(dāng)有任何進(jìn)程想要寫時,它必須在更新過程中鎖住數(shù)據(jù)庫文件。 但那通常只是幾毫秒的時間。其它進(jìn)程只需等待寫進(jìn)程干完活結(jié)束。典型地,其它嵌入式的SQL數(shù)據(jù)庫引擎同時只允許一個進(jìn)程連接到數(shù)據(jù)庫。
但是,Client/Server數(shù)據(jù)庫引擎(如
PostgreSQL, MySQL, 或 Oracle)通常支持更高級別的并發(fā),并且允許多個進(jìn)程同時寫同一個數(shù)據(jù)庫。
這種機(jī)制在Client/Server結(jié)構(gòu)的數(shù)據(jù)庫上是可能的,因為總是有一個單一的服務(wù)器進(jìn)程很好地控制、協(xié)調(diào)對數(shù)據(jù)庫的訪問。如果你的應(yīng)用程序需要很
多的并發(fā),那么你應(yīng)該考慮使用一個Client/Server 結(jié)構(gòu)的數(shù)據(jù)庫。但經(jīng)驗表明,很多應(yīng)用程序需要的并發(fā),往往比其設(shè)計者所想象的少得多。
當(dāng)SQLite 試圖訪問一個被其它進(jìn)程鎖住的文件時,缺省的行為是返回 SQLITE_BUSY。 可以在C代碼中使用 sqlite3_busy_handler() 或 sqlite3_busy_timeout() API 函數(shù)調(diào)整這一行為。
在SQLite 數(shù)據(jù)庫中如何列出所有的表和索引?
如果你運(yùn)行 sqlite3 命令行來訪問你的數(shù)據(jù)庫,可以鍵入 “.tables”來獲得所有表的列表?;蛘?,你可以輸入 “.schema” 來看整個數(shù)據(jù)庫模式,包括所有的表的索引。 輸入這些命令,后面跟一個LIKE模式匹配可以限制顯示的表。
在一個 C/C++ 程序中(或者腳本語言使用 Tcl/Ruby/Perl/Python 等) 你可以在一個特殊的名叫 SQLITE_MASTER 上執(zhí)行一個SELECT查詢以獲得所有 表的索引。每一個 SQLite 數(shù)據(jù)庫都有一個叫 SQLITE_MASTER 的表, 它定義數(shù)據(jù)庫的模式。 SQLITE_MASTER 表看起來如下:
CREATE TABLE sqlite_master (
type TEXT,
name TEXT,
tbl_name TEXT,
rootpage INTEGER,
sql TEXT
);
對于表來說,type 字段永遠(yuǎn)是 'table',name 字段永遠(yuǎn)是表的名字。所以,要獲得數(shù)據(jù)庫中所有表的列表, 使用下列SELECT語句:
SELECT name FROM sqlite_master
WHERE type='table'
ORDER BY name;
對于索引,type 等于 'index', name 則是索引的名字,tbl_name 是該索引所屬的表的名字。 不管是表還是索引,sql
字段是原先用 CREATE TABLE 或 CREATE INDEX 語句創(chuàng)建它們時的命令文本。對于自動創(chuàng)建的索引(用來實現(xiàn) PRIMARY
KEY 或 UNIQUE 約束),sql字段為NULL。
SQLITE_MASTER 表是只讀的。不能對它使用 UPDATE、INSERT 或 DELETE。 它會被 CREATE TABLE、CREATE INDEX、DROP TABLE 和 DROP INDEX 命令自動更新。
臨時表不會出現(xiàn)在 SQLITE_MASTER
表中。臨時表及其索引和觸發(fā)器存放在另外一個叫 SQLITE_TEMP_MASTER 的表中。SQLITE_TEMP_MASTER 跟
SQLITE_MASTER 差不多,但它只是對于創(chuàng)建那些臨時表的應(yīng)用可見。如果要獲得所有表的列表,
不管是永久的還是臨時的,可以使用類似下面的命令:
SELECT name FROM
(SELECT * FROM sqlite_master UNION ALL
SELECT * FROM sqlite_temp_master)
WHERE type='table'
ORDER BY name
在SQLite 中,VARCHAR字段最長是多少?
SQLite 不強(qiáng)制 VARCHAR 的長度。 你可以在 SQLITE 中聲明一個 VARCHAR(10),SQLite 還是可以很高興地允許你放入500個字符。 并且這500個字符是原封不動的,它永遠(yuǎn)不會被截斷。
SQLite 支持二進(jìn)制大對象嗎?
SQLite 3.0 及以后版本允許你在任何列中存儲 BLOB 數(shù)據(jù)。 即使該列被聲明為其它類型也可以。
在SQLite 中,如何在一個表上添加或刪除一列?
SQLite 有有限地 ALTER TABLE 支持。你可以使用它來在表的末尾增加一列,可更改表的名稱。 如果需要對表結(jié)構(gòu)做更復(fù)雜的改變,則必須重新建表。 重建時可以先將已存在的數(shù)據(jù)放到一個臨時表中,刪除原表, 創(chuàng)建新表,然后將數(shù)據(jù)從臨時表中復(fù)制回來。
如,假設(shè)有一個 t1 表,其中有 "a", "b", "c" 三列, 如果要刪除列 c ,以下過程描述如何做:
BEGIN TRANSACTION;
CREATE TEMPORARY TABLE t1_backup(a,b);
INSERT INTO t1_backup SELECT a,b FROM t1;
DROP TABLE t1;
CREATE TABLE t1(a,b);
INSERT INTO t1 SELECT a,b FROM t1_backup;
DROP TABLE t1_backup;
COMMIT;
在數(shù)據(jù)庫中刪除了很多數(shù)據(jù),但數(shù)據(jù)庫文件沒有變小,是Bug嗎?
不是。當(dāng)你從SQLite 數(shù)據(jù)庫中刪除數(shù)據(jù)時, 未用的磁盤空間將會加入一個內(nèi)部的“自由列表”中。 當(dāng)你下次插入數(shù)據(jù)時,這部分空間可以重用。磁盤空間不會丟失, 但也不會返還給操作系統(tǒng)。
如果刪除了大量數(shù)據(jù),而又想縮小數(shù)據(jù)庫文件占用的空間,執(zhí)行 VACUUM 命令。 VACUUM 將會從頭重新組織數(shù)據(jù)庫。這將會使用數(shù)據(jù)庫有一個空的“自由鏈表”, 數(shù)據(jù)庫文件也會最小。但要注意的是,VACUUM 的執(zhí)行會需要一些時間(在SQLite 開發(fā)時,在Linux上,大約每M字節(jié)需要半秒種),并且, 執(zhí)行過程中需要原數(shù)據(jù)庫文件至多兩倍的臨時磁盤空間。
對于 SQLite 3.1版本,一個 auto-vacumm 模式可以替代 VACUUM 命令。 可以使用 auto_vacuum pragma 打開。
SQLITE_SCHEMA error是什么錯誤?為什么會出現(xiàn)該錯誤?
當(dāng)一個準(zhǔn)備好的(prepared)SQL語句不再有效或者無法執(zhí)行時, 將返回一個 SQLITE_SCHEMA 錯誤。發(fā)生該錯誤時,SQL語句必須使用 sqlite3_prepare() API來重新編譯. 在 SQLite
3 中, 一個 SQLITE_SCHEMA 錯誤只會發(fā)生在用
sqlite3_prepare()/sqlite3_step()/sqlite3_finalize() API 執(zhí)行 SQL
時。而不會發(fā)生在使用 sqlite3_exec()時。 在版本2中不是這樣。
準(zhǔn)備好的語句失效的最通常原因是:在語句準(zhǔn)備好后, 數(shù)據(jù)庫的模式又被修改了。另外的原因會發(fā)生在:
數(shù)據(jù)庫離線:DETACHed.
數(shù)據(jù)庫被 VACUUMed
一個用戶存儲過程定義被刪除或改變。
一個 collation 序列定義被刪除或改變。
認(rèn)證函數(shù)被改變。
在所有情況下,解決方法是重新編譯并執(zhí)行該SQL語句。 因為一個已準(zhǔn)備好的語句可以由于其它進(jìn)程改變數(shù)據(jù)庫模式而失效, 所有使用
sqlite3_prepare()/sqlite3_step()/sqlite3_finalize() API 的代碼都應(yīng)準(zhǔn)備處理
SQLITE_SCHEMA 錯誤。下面給出一個例子:
int rc;
sqlite3_stmt *pStmt;
char zSql[] = "SELECT .....";
do {
/* Compile the statement from SQL. Assume success. */
sqlite3_prepare(pDb, zSql, -1, &pStmt, 0);
while( SQLITE_ROW==sqlite3_step(pStmt) ){
/* Do something with the row of available data */
}
/* Finalize the statement. If an SQLITE_SCHEMA error has
** occured, then the above call to sqlite3_step() will have
** returned SQLITE_ERROR. sqlite3_finalize() will return
** SQLITE_SCHEMA. In this case the loop will execute again.
*/
rc = sqlite3_finalize(pStmt);
} while( rc==SQLITE_SCHEMA );
|