目錄


查詢的資料中含有空值 Null

現有一個 credit_cards 資料表,想找出符合下面幾個條件的資料:

  1. payment 沒有值
  2. 或者 check_date 沒有值
  3. 排除 source = ‘TEST’ 的資料

In credit_cards table:

idstatusbanknopaymentcheck_datesource
1‘V’123nullnullSTORE
2‘V’123nullnullnull
3‘V’123nullnullPHONE
4‘V’123‘A’20191122TEST
5‘V’123‘A’20191122STORE

原本嘗試透過這段查詢搜尋,但結果不盡人意:

# Option 1
CreditCard.where('payment IS NULL OR check_date IS NULL AND source != ?', 'TEST')

# option 2 - Find by ActiveRecord query:
CreditCard.where(payment: nil)
          .or(CreditCard.where(payment: nil))
          .where.not(source: 'TEST')

很快地發現第二列資料並沒有如預期的被列出出來,這並不是我們要的結果。

因為資料中有些記錄的 source 欄位還沒有值,本以為透過 source != TEST 這個條件下搜尋應該能比對出結果,看來案情不單純。

查了一下發現 SQL 對待空值和對待其他值的處理方式不同,所以就不能直接拿來做字串的比對, 在這裡我們必須指名道姓的對資料庫說要 Null 出來面對 (WHERE … IS NULL),故修改最終查詢子句如下:

# Option 1
CreditCard.where('payment IS NULL OR check_date IS NULL AND source != ? OR source IS NULL', 'TEST')

# option 2 - Find by ActiveRecord query:
CreditCard.where(payment: nil)
          .or(CreditCard.where(payment: nil))
          .where.not(source: 'TEST')
          .or(CreditCard.where(source: nil))

IS NULL

Null(空值)是結構化查詢語言 SQL 中使用的特殊標記,用於表示資料庫中不具值,它不是一個值,而應該說是一個『狀態』,用作資料庫欄位的預設值、資料缺失或不可用。

正因為 Null 不是數據,而是一種資料缺失的標記,所以用於算術運算將會得出未知結果。

查詢時的 WHERE 條件式要判斷欄位是否為 Null 時,用 WHERE payment = NULL 是沒有用的,必須寫成 WHERE payment IS NULL,同理,前面例子中 source != TEST 也是因為 Null 在運算中被資料庫忽略而沒有達到預期的效果,所以必須再串一個針對 Null 的 OR 查詢子句。

參考

  • 空值 (SQL) - 維基百科
  • 《圖解資料庫系統理論:使用 MySQL 實作》 - 李春雄
⤧  Previous post ActiveRecord - Associations 資料表間的關聯 ⤧  Next post Rails - alias & alias_mehtod 的用法和區別