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