2014-03-27 47 views
15

我注意到在具有UNIQUE約束的列中可以有NULL值:UNIQUE(col)Sqlite NULL和唯一?

在某些情況下會產生任何問題嗎?

+0

像什麼情況? btw什麼是數據類型? – KrazzyNefarious

+1

「在某些情況下會產生任何問題嗎?」可能 - 你關心哪些情況? –

+0

就像做任何類型的數據庫操作一樣。我會得到任何錯誤嗎?當我不再需要它們時,我正在考慮將記錄設置爲NULL。問題是,刪除它們需要很長時間,我寧願在cron作業中執行此操作。 – katie

回答

20

雖然下面的地址的多個空值,它地址的任何「問題」這樣的設計有關,除了可能的數據庫/ SQL的可移植性等 - 因此,它或許應該被認爲是一個答案,並留在這裏僅供參考。


這實際上在SQLite FAQ中已經介紹過了。這是一個設計選擇--SQLite(與SQL Server不同)選擇多個NULL值不會計入索引中的唯一性。

The SQL standard requires that a UNIQUE constraint be enforced even if one or more of the columns in the constraint are NULL, but SQLite does not do this. Isn't that a bug?

也許你指的是下面的語句SQL92:

  • 獨特的滿足約束條件當且僅當在一個表中沒有兩行具有相同的非空值在獨特的專欄中。

這種說法是不明確的,至少有兩種可能的解釋:

  1. 獨特的滿足約束條件當且僅當在一個表中沒有兩行具有相同的價值觀,並具有非空值在獨特的專欄中。

  2. 當且僅當表中沒有兩個行在非空的唯一列的子集中具有相同的值時,滿足唯一約束。

與PostgreSQL,MySQL,Oracle和Firebird一樣,SQLite遵循解釋(1)。的確,Informix和Microsoft SQL Server使用解釋(2),但是我們SQLite開發人員認爲解釋(1)是對需求的最自然的解讀,我們也希望最大化與其他SQL數據庫引擎的兼容性,以及大多數其他數據庫引擎也與(1)一起使用,所以這就是SQLite所做的。

請參閱comparison of NULL handling

2

您可以在表上創建2個觸發器,以檢查在任何插入或更新操作之前是否存在具有列爲空的行,如果發生異常。

CREATE TRIGGER UniqueColumnCheckNullInsert 
     BEFORE INSERT 
     ON 'Tablename' 
     WHEN NEW.'column_name' IS NULL 
     BEGIN 
     SELECT CASE WHEN((
      SELECT 1 
      FROM 'Tablename' 
      WHERE 'column_name' IS NULL 
      ) 
      NOTNULL) THEN RAISE(ABORT, "error row exists") END; 
    END; 

CREATE TRIGGER UniqueColumnCheckNullUpdate 
     BEFORE UPDATE 
     ON 'Tablename' 
     WHEN NEW.'column_name' IS NULL 
     BEGIN 
     SELECT CASE WHEN((
      SELECT 1 
      FROM 'Tablename' 
      WHERE 'column_name' IS NULL 
      ) 
      NOTNULL) THEN RAISE(ABORT, "error row exists") END; 
    END;