我的目標是使SQLite用一種標準和順從的方法來處理空值。但是在SQL標準中關(guān)于如何處理空值的描述似乎不太明確。從標準文檔中,我們不太容易弄清楚空值在所有場合下是如何被處理的。
所以標準文檔被取代,各種流行的SQL引擎被用來測試,看它們是如何處理空值的。我的目的是想SQLite像其他引擎一樣工作。志愿者們開發(fā)了 SQL的測試腳本并使之在SQL RDBMSes上運行,運用測試的結(jié)果來推論空值在各種引擎上是如何被處理的。最初的測試是在2002年5月運行的。測試腳本的副本在這篇文檔的最后。
SQLite最初是這樣編譯的,對于下面表格中的所有問題,它的答案都是"Yes"。 但是在其它SQL引擎上的測試表明沒有一個引擎是這樣工作的。所以SQLite被改進了,改進后它像Oracle, PostgreSQL, and DB2一樣工作。改進后,對于SELECT DISTINCT 語句和SELECT中的UNIQUE操作符,空值是模糊的。在UNIQUE列中空值仍然是清晰的。這看起來有些獨裁的意思,但是使SQLite和其它數(shù)據(jù) 庫引擎兼容似乎比這個缺陷更重要。
為了SELECT DISTINCT和UNION,使SQLite認為空值是清晰的是有可能的。但是你需要在sqliteInt.h原文件中改變NULL_ALWAYS_DISTINCT #define的值,并重新編譯。
更新于2003-07-13: 這篇文檔寫的很早,一些被測試的數(shù)據(jù)庫引擎已經(jīng)被更新,忠實地使用者也發(fā)送了一些關(guān)于下面表格的修正意見。原始數(shù)據(jù)顯示了各種不同的狀態(tài),但是隨著時間的 變化,數(shù)據(jù)的狀態(tài)已經(jīng)逐漸向PostgreSQL/Oracle模式匯合。唯一的突出的不同是Informix and MS-SQL在UNIQUE列中都認為空值是模糊的。
令人迷惑的一點是,NULLs對于UNIQUE列是清晰的,但對于 SELECT DISTINCT和UNION是模糊的??罩祽?yīng)該是清晰或模糊都可以。但SQL標準文檔建議空值在所有地方都是清晰的。 但在這篇作品中,被測試的SQL引擎認為在SELECT DISTINCT或在UNION中,空值是清晰的。
下面的表格顯示了空處理實驗的結(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)于上面表格的信息。
-- 我認為SQL關(guān)于空值的處理是不定的,所以不能靠邏輯來推斷,必須同過實驗來發(fā)現(xiàn)結(jié)果。為了實現(xiàn)這個目標,我已經(jīng)準備了下列的腳本來測試不同的SQL數(shù)據(jù)庫如何處理空值。
新聞熱點
疑難解答
圖片精選