php SQLite學(xué)習(xí)筆記與常見(jiàn)問(wèn)題分析第2/2頁(yè)
更新時(shí)間:2008年07月23日 19:22:44 作者:
php SQLite學(xué)習(xí)資料收集,與一些常見(jiàn)問(wèn)題的解決方法
(6)SQLite線程安全嗎?
線程是魔鬼(Threads are evil)。 避免使用它們。
SQLite 是線程安全的。由于很多用戶會(huì)忽略我們?cè)谏弦欢沃薪o出的建議, 我們做出了這種讓步。但是,為了達(dá)到線程安全,SQLite在編譯時(shí)必須將 SQLITE_THREADSAFE 預(yù)處理宏置為1。在Windows和Linux上,已編譯的好的二進(jìn)制發(fā)行版中都是這樣設(shè)置的。如果不確定你所使用的庫(kù)是否是線程安全的,可以調(diào)用 sqlite3_threadsafe() 接口找出。
在 3.3.1 版本之前,一個(gè) sqlite3 結(jié)構(gòu)只能被用于調(diào)用 sqlite3_open 創(chuàng)建的同一線程。你不能在一個(gè)線程中打開數(shù)據(jù)庫(kù),然后將數(shù)據(jù)庫(kù)句柄傳遞給另外一個(gè)進(jìn)程使用。這主要是由于在好多通用的線程實(shí)現(xiàn)(如RedHat9)中的限制引起的(是Bug嗎?)。特別的,在有問(wèn)題的系統(tǒng)上,一個(gè)進(jìn)程創(chuàng)建的 fcntl() 鎖無(wú)法被其它線程清除或修改。 所以,由于 SQLite 大量使用 fcntl() 鎖做并發(fā)控制,如果你在不同的線程間移動(dòng)數(shù)據(jù)庫(kù)連接,就可能會(huì)出現(xiàn)嚴(yán)重的問(wèn)題。
在3.3.1版本上,關(guān)于在線程間移動(dòng)數(shù)據(jù)庫(kù)連接的限制變得寬松了。 在它及以后的版本中,只要連接沒(méi)有持有 fcntl() 鎖,在線程間移動(dòng)句柄是安全的。 如果沒(méi)有未決的事務(wù),并且所有的語(yǔ)句都已執(zhí)行完畢, 你就可以安全的假定不再持有任何鎖。
在UNIX中,在執(zhí)行 fork() 系統(tǒng)調(diào)用時(shí)不應(yīng)攜帶已打開的數(shù)據(jù)庫(kù)進(jìn)入子進(jìn)程。 那樣做將會(huì)有問(wèn)題。
--------------------------------------------------------------------------------
(7)在SQLite數(shù)據(jù)庫(kù)中如何列出所有的表和索引?
如果你運(yùn)行 sqlite3 命令行來(lái)訪問(wèn)你的數(shù)據(jù)庫(kù),可以鍵入 “.tables”來(lái)獲得所有表的列表?;蛘撸憧梢暂斎?nbsp;“.schema” 來(lái)看整個(gè)數(shù)據(jù)庫(kù)模式,包括所有的表的索引。 輸入這些命令,后面跟一個(gè)LIKE模式匹配可以限制顯示的表。
在一個(gè) C/C++ 程序中(或者腳本語(yǔ)言使用 Tcl/Ruby/Perl/Python 等) 你可以在一個(gè)特殊的名叫 SQLITE_MASTER 上執(zhí)行一個(gè)SELECT查詢以獲得所有 表的索引。每一個(gè) SQLite 數(shù)據(jù)庫(kù)都有一個(gè)叫 SQLITE_MASTER 的表,它定義數(shù)據(jù)庫(kù)的模式。 SQLITE_MASTER 表看起來(lái)如下:
CREATE TABLE sqlite_master (
type TEXT,
name TEXT,
tbl_name TEXT,
rootpage INTEGER,
sql TEXT
);
對(duì)于表來(lái)說(shuō),type 字段永遠(yuǎn)是 'table',name 字段永遠(yuǎn)是表的名字。所以,要獲得數(shù)據(jù)庫(kù)中所有表的列表, 使用下列SELECT語(yǔ)句:
SELECT name FROM sqlite_master
WHERE type='table'
ORDER BY name;
對(duì)于索引,type 等于 'index', name 則是索引的名字,tbl_name 是該索引所屬的表的名字。 不管是表還是索引,sql 字段是原先用 CREATE TABLE 或 CREATE INDEX 語(yǔ)句創(chuàng)建它們時(shí)的命令文本。對(duì)于自動(dòng)創(chuàng)建的索引(用來(lái)實(shí)現(xiàn) PRIMARY KEY 或 UNIQUE 約束),sql字段為NULL。
SQLITE_MASTER 表是只讀的。不能對(duì)它使用 UPDATE、INSERT 或 DELETE。 它會(huì)被 CREATE TABLE、CREATE INDEX、DROP TABLE 和 DROP INDEX 命令自動(dòng)更新。
臨時(shí)表不會(huì)出現(xiàn)在 SQLITE_MASTER 表中。臨時(shí)表及其索引和觸發(fā)器存放在另外一個(gè)叫 SQLITE_TEMP_MASTER 的表中。SQLITE_TEMP_MASTER 跟 SQLITE_MASTER 差不多,但它只是對(duì)于創(chuàng)建那些臨時(shí)表的應(yīng)用可見(jiàn)。如果要獲得所有表的列表, 不管是永久的還是臨時(shí)的,可以使用類似下面的命令:
SELECT name FROM
(SELECT * FROM sqlite_master UNION ALL
SELECT * FROM sqlite_temp_master)
WHERE type='table'
ORDER BY name
--------------------------------------------------------------------------------
(8) SQLite數(shù)據(jù)庫(kù)有已知的大小限制嗎?
在 Windows 和 Unix 下,版本 2.7.4的 SQLite 可以達(dá)到 2的41次方字節(jié) (2T 字節(jié))。老版本的為 2的31 次方字節(jié)(2G 字節(jié))。
SQLite 版本 2.8 限制一個(gè)記錄的容量為 1M。SQLite 版本 3.0 則對(duì)單個(gè)記錄容量沒(méi)有限制。
表名、索引表名、視圖名、觸發(fā)器名和字段名沒(méi)有長(zhǎng)度限制。但 SQL 函數(shù)的名稱 (由 sqlite3_create_function() API 函數(shù)創(chuàng)建) 不得超過(guò) 255 個(gè)字符。
對(duì)有關(guān)SQLite限制的詳細(xì)討論,見(jiàn) limits.html 。
--------------------------------------------------------------------------------
(9) 在SQLite中,VARCHAR字段最長(zhǎng)是多少?
SQLite 不強(qiáng)制 VARCHAR 的長(zhǎng)度。 你可以在 SQLITE 中聲明一個(gè) VARCHAR(10),SQLite還是可以很高興地允許你放入500個(gè)字符。 并且這500個(gè)字符是原封不動(dòng)的,它永遠(yuǎn)不會(huì)被截?cái)唷?
--------------------------------------------------------------------------------
(10) SQLite支持二進(jìn)制大對(duì)象嗎?
SQLite 3.0 及以后版本允許你在任何列中存儲(chǔ) BLOB 數(shù)據(jù)。 即使該列被聲明為其它類型也可以。
--------------------------------------------------------------------------------
(11) 在SQLite中,如何在一個(gè)表上添加或刪除一列?
SQLite 有有限地 ALTER TABLE 支持。你可以使用它來(lái)在表的末尾增加一列,可更改表的名稱。 如果需要對(duì)表結(jié)構(gòu)做更復(fù)雜的改變,則必須重新建表。 重建時(shí)可以先將已存在的數(shù)據(jù)放到一個(gè)臨時(shí)表中,刪除原表, 創(chuàng)建新表,然后將數(shù)據(jù)從臨時(shí)表中復(fù)制回來(lái)。
如,假設(shè)有一個(gè) t1 表,其中有 "a", "b", "c" 三列, 如果要?jiǎng)h除列 c ,以下過(guò)程描述如何做:
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;
--------------------------------------------------------------------------------
(12) 我在數(shù)據(jù)庫(kù)中刪除了很多數(shù)據(jù),但數(shù)據(jù)庫(kù)文件沒(méi)有變小,是Bug嗎?
不是。當(dāng)你從SQLite數(shù)據(jù)庫(kù)中刪除數(shù)據(jù)時(shí), 未用的磁盤空間將會(huì)加入一個(gè)內(nèi)部的“自由列表”中。 當(dāng)你下次插入數(shù)據(jù)時(shí),這部分空間可以重用。磁盤空間不會(huì)丟失, 但也不會(huì)返還給操作系統(tǒng)。
如果刪除了大量數(shù)據(jù),而又想縮小數(shù)據(jù)庫(kù)文件占用的空間,執(zhí)行 VACUUM 命令。 VACUUM 將會(huì)從頭重新組織數(shù)據(jù)庫(kù)。這將會(huì)使用數(shù)據(jù)庫(kù)有一個(gè)空的“自由鏈表”, 數(shù)據(jù)庫(kù)文件也會(huì)最小。但要注意的是,VACUUM 的執(zhí)行會(huì)需要一些時(shí)間(在SQLite開發(fā)時(shí),在Linux上,大約每M字節(jié)需要半秒種),并且,執(zhí)行過(guò)程中需要原數(shù)據(jù)庫(kù)文件至多兩倍的臨時(shí)磁盤空間。
對(duì)于 SQLite 3.1版本,一個(gè) auto-vacumm 模式可以替代 VACUUM 命令。 可以使用 auto_vacuum pragma 打開。
--------------------------------------------------------------------------------
(13) 我可以在商業(yè)產(chǎn)品中使用SQLite而不需支付許可費(fèi)用嗎?
是的。SQLite 在 public domain。 對(duì)代碼的任何部分沒(méi)有任何所有權(quán)聲明。你可以使用它做任何事。
--------------------------------------------------------------------------------
(14) 如何在字符串中使用單引號(hào)(')?
SQL 標(biāo)準(zhǔn)規(guī)定,在字符串中,單引號(hào)需要使用逃逸字符,即在一行中使用兩個(gè)單引號(hào)。在這方面 SQL 用起來(lái)類似 Pascal 語(yǔ)言。 SQLite 尊循標(biāo)準(zhǔn)。如:
INSERT INTO xyz VALUES('5 O''clock');
--------------------------------------------------------------------------------
(15) SQLITE_SCHEMA error是什么錯(cuò)誤?為什么會(huì)出現(xiàn)該錯(cuò)誤?
當(dāng)一個(gè)準(zhǔn)備好的(prepared)SQL語(yǔ)句不再有效或者無(wú)法執(zhí)行時(shí), 將返回一個(gè) SQLITE_SCHEMA 錯(cuò)誤。發(fā)生該錯(cuò)誤時(shí),SQL語(yǔ)句必須使用 sqlite3_prepare() API來(lái)重新編譯. 在 SQLite 3 中, 一個(gè) SQLITE_SCHEMA 錯(cuò)誤只會(huì)發(fā)生在用 sqlite3_prepare()/sqlite3_step()/sqlite3_finalize() API 執(zhí)行 SQL 時(shí)。而不會(huì)發(fā)生在使用 sqlite3_exec()時(shí)。 在版本2中不是這樣。
準(zhǔn)備好的語(yǔ)句失效的最通常原因是:在語(yǔ)句準(zhǔn)備好后, 數(shù)據(jù)庫(kù)的模式又被修改了。另外的原因會(huì)發(fā)生在:
數(shù)據(jù)庫(kù)離線:DETACHed.
數(shù)據(jù)庫(kù)被 VACUUMed
一個(gè)用戶存儲(chǔ)過(guò)程定義被刪除或改變。
一個(gè) collation 序列定義被刪除或改變。
認(rèn)證函數(shù)被改變。
在所有情況下,解決方法是重新編譯并執(zhí)行該SQL語(yǔ)句。 因?yàn)橐粋€(gè)已準(zhǔn)備好的語(yǔ)句可以由于其它進(jìn)程改變數(shù)據(jù)庫(kù)模式而失效, 所有使用 sqlite3_prepare()/sqlite3_step()/sqlite3_finalize() API 的代碼都應(yīng)準(zhǔn)備處理 SQLITE_SCHEMA 錯(cuò)誤。下面給出一個(gè)例子:
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 );
--------------------------------------------------------------------------------
(16) 為什么 ROUND(9.95,1) 返回 9.9 而不是 10.0? 9.95不應(yīng)該圓整 (四舍五入)嗎?
SQLite 使用二進(jìn)制算術(shù),在二進(jìn)制中, 無(wú)法用有限的二進(jìn)制位數(shù)表示 9.95 。使用 64-bit IEEE 浮點(diǎn) (SQLite就是使用這個(gè))最接近 9.95 的二進(jìn)制表示是 9.949999999999999289457264239899814128875732421875。所在,當(dāng)你輸入 9.95 時(shí),SQLite實(shí)際上以為是上面的數(shù)字, 在四舍五入時(shí)會(huì)舍去。
這種問(wèn)題在使用二進(jìn)制浮點(diǎn)數(shù)的任何時(shí)候都會(huì)出現(xiàn)。 通常的規(guī)則是記住很多有限的十進(jìn)制小數(shù)都沒(méi)有一個(gè)對(duì)應(yīng)的二進(jìn)制表示。 所以,它們只能使用最接近的二進(jìn)制數(shù)。它們通常非常接近, 但也會(huì)有些微小的不同,有些時(shí)候也會(huì)導(dǎo)致你所期望的不同的結(jié)果。
相關(guān)文章
php dirname(__FILE__) 獲取當(dāng)前文件的絕對(duì)路徑
dirname(__FILE__) 取到的是當(dāng)前文件的絕對(duì)路徑,也就是說(shuō),比起相對(duì)路徑,查找速度是最快的。2011-06-06PHP垃圾回收機(jī)制引用計(jì)數(shù)器概念分析
php變量存在一個(gè)叫"zval"的變量容器中,"zval"變量容器包括含變量的類型和值,還包括額外的兩個(gè)字節(jié)信息,分別是“is_ref”表示變量是否屬于引用,“refcount”指向這個(gè)zval變量容器的變量個(gè)數(shù)2013-06-06關(guān)于php程序報(bào)date()警告的處理(date_default_timezone_set)
PHP Warning: date(): It is not safe to rely on the system's timezone settings. You are *required* to use the date.timezone setting or the date_default_timezone_set() function2013-10-10PHP實(shí)現(xiàn)的mongoDB數(shù)據(jù)庫(kù)操作類完整實(shí)例
這篇文章主要介紹了PHP實(shí)現(xiàn)的mongoDB數(shù)據(jù)庫(kù)操作類,結(jié)合完整實(shí)例形式詳細(xì)分析了php基于單例模式針對(duì)mongoDB數(shù)據(jù)庫(kù)連接、增刪改查、統(tǒng)計(jì)等操作相關(guān)實(shí)現(xiàn)技巧,需要的朋友可以參考下2018-04-04Joomla下利用configuration.php存儲(chǔ)簡(jiǎn)單數(shù)據(jù)
Joomla下利用configuration.php存儲(chǔ)簡(jiǎn)單數(shù)據(jù)的代碼,需要的朋友可以參考下。2010-05-05PHP實(shí)現(xiàn)的分解質(zhì)因數(shù)操作示例
這篇文章主要介紹了PHP實(shí)現(xiàn)的分解質(zhì)因數(shù)操作,結(jié)合實(shí)例形式分析了php實(shí)現(xiàn)分解質(zhì)因數(shù)的相關(guān)原理、步驟與操作技巧,需要的朋友可以參考下2018-08-08