我的目標(biāo)是使SQLite用一種標(biāo)準(zhǔn)和順從的方法來處理空值。但是在SQL標(biāo)準(zhǔn)中關(guān)于如何處理空值的描述似乎不太明確。從標(biāo)準(zhǔn)文檔中,我們不太容易弄清楚空值在所有場合下是如何被處理的。
所以標(biāo)準(zhǔn)文檔被取代,各種流行的SQL引擎被用來測試,看它們是如何處理空值的。我的目的是想SQLite像其他引擎一樣工作。志愿者們開發(fā)了 SQL的測試腳本并使之在SQL RDBMSes上運(yùn)行,運(yùn)用測試的結(jié)果來推論空值在各種引擎上是如何被處理的。最初的測試是在2002年5月運(yùn)行的。測試腳本的副本在這篇文檔的最后。
SQLite最初是這樣編譯的,對于下面表格中的所有問題,它的答案都是"Yes"。 但是在其它SQL引擎上的測試表明沒有一個引擎是這樣工作的。所以SQLite被改進(jìn)了,改進(jìn)后它像Oracle, PostgreSQL, and DB2一樣工作。改進(jìn)后,對于SELECT DISTINCT 語句和SELECT中的UNIQUE操作符,空值是模糊的。在UNIQUE列中空值仍然是清晰的。這看起來有些獨(dú)裁的意思,但是使SQLite和其它數(shù)據(jù) 庫引擎兼容似乎比這個缺陷更重要。
為了SELECT DISTINCT和UNION,使SQLite認(rèn)為空值是清晰的是有可能的。但是你需要在sqliteInt.h原文件中改變NULL_ALWAYS_DISTINCT #define的值,并重新編譯。
更新于2003-07-13: 這篇文檔寫的很早,一些被測試的數(shù)據(jù)庫引擎已經(jīng)被更新,忠實(shí)地使用者也發(fā)送了一些關(guān)于下面表格的修正意見。原始數(shù)據(jù)顯示了各種不同的狀態(tài),但是隨著時間的 變化,數(shù)據(jù)的狀態(tài)已經(jīng)逐漸向PostgreSQL/Oracle模式匯合。唯一的突出的不同是Informix and MS-SQL在UNIQUE列中都認(rèn)為空值是模糊的。
令人迷惑的一點(diǎn)是,NULLs對于UNIQUE列是清晰的,但對于 SELECT DISTINCT和UNION是模糊的??罩祽?yīng)該是清晰或模糊都可以。但SQL標(biāo)準(zhǔn)文檔建議空值在所有地方都是清晰的。 但在這篇作品中,被測試的SQL引擎認(rèn)為在SELECT DISTINCT或在UNION中,空值是清晰的。
下面的表格顯示了空處理實(shí)驗(yàn)的結(jié)果。
SQLite | PostgreSQL | Oracle | Informix | DB2 | MS-SQL | OCELOT | |
---|---|---|---|---|---|---|---|
Adding anything to null gives null | Yes | Yes | Yes | Yes | Yes | Yes | Yes |
Multiplying null by zero gives null | Yes | Yes | Yes | Yes | Yes | Yes | Yes |
nulls are distinct in a UNIQUE column | Yes | Yes | Yes | No | (Note 4) | No | Yes |
nulls are distinct in SELECT DISTINCT | No | No | No | No | No | No | No |
nulls are distinct in a UNION | No | No | No | No | No | No | No |
"CASE WHEN null THEN 1 ELSE 0 END" is 0? | Yes | Yes | Yes | Yes | Yes | Yes | Yes |
"null OR true" is true | Yes | Yes | Yes | Yes | Yes | Yes | Yes |
"not (null AND false)" is true | Yes | Yes | Yes | Yes | Yes | Yes | Yes |
MySQL 3.23.41 | MySQL 4.0.16 | Firebird | SQL Anywhere | Borland Interbase | |
---|---|---|---|---|---|
Adding anything to null gives null | Yes | Yes | Yes | Yes | Yes |
Multiplying null by zero gives null | Yes | Yes | Yes | Yes | Yes |
nulls are distinct in a UNIQUE column | Yes | Yes | Yes | (Note 4) | (Note 4) |
nulls are distinct in SELECT DISTINCT | No | No | No (Note 1) | No | No |
nulls are distinct in a UNION | (Note 3) | No | No (Note 1) | No | No |
"CASE WHEN null THEN 1 ELSE 0 END" is 0? | Yes | Yes | Yes | Yes | (Note 5) |
"null OR true" is true | Yes | Yes | Yes | Yes | Yes |
"not (null AND false)" is true | No | Yes | Yes | Yes | Yes |
Notes: | 1. | Older versions of firebird omits all NULLs from SELECT DISTINCT and from UNION. |
2. | Test data unavailable. | |
3. | MySQL version 3.23.41 does not support UNION. | |
4. | DB2, SQL Anywhere, and Borland Interbase do not allow NULLs in a UNIQUE column. | |
5. | Borland Interbase does not support CASE expressions. |
下面的腳本被用來收集關(guān)于上面表格的信息。
-- 我認(rèn)為SQL關(guān)于空值的處理是不定的,所以不能靠邏輯來推斷,必須同過實(shí)驗(yàn)來發(fā)現(xiàn)結(jié)果。為了實(shí)現(xiàn)這個目標(biāo),我已經(jīng)準(zhǔn)備了下列的腳本來測試不同的SQL數(shù)據(jù)庫如何處理空值。
新聞熱點(diǎn)
疑難解答
圖片精選