2009-06-30 91 views
1

我是python的新手,並且遇到了一個我試圖執行的SQL查詢的問題。Python SQL選擇可能的NULL值

我創建的填充值從數組如下SQL SELECT語句:

ret = conn.execute('SELECT * FROM TestTable WHERE a = ? b = ? c = ?', *values) 

該工程確定在那裏我有數值數組中的實際值。但是,在某些情況下,值中的單個條目可能設置爲無。查詢然後失敗,因爲「= NULL」測試不起作用,因爲測試應該是IS NULL。

有沒有簡單的方法呢?

回答

1

如果您正在使用SQL Server,然後只要你設置ANSI_NULLS關閉會話「= NULL」比較將工作。

SET ANSI_NULLS

+0

這是一個很好的簡單解決方案,工作正常。非常感謝! – JamieH 2009-06-30 14:33:36

3

使用:「從TestTable的選擇*其中(A =或爲空?)和(b =或b爲空?)」

這將選擇情況下,一所提供的值完全匹配,將包括列中的空值 - 如果這是你想要的。

+0

另外,Python值`None`等價於SQL`NULL`。 – 2009-06-30 14:04:58

0

如果你覺得冒險,你也可以看看SQLAlchemy。它在很多其他的東西中提供了一個SQL構建工具包,可以自動將比較轉換爲無到IS NULL操作。

1

您可以隨時使用三元運算爲 'IS' 切換 '=':

("=","IS")[var is None] 

將返回 「IS」 如果VAR是無與 「=」,否則。

這不是很高雅做的這一條線,雖然,但只是爲了證明:

query = "SELECT * FROM testTable WHERE a %s %s" % (("=","IS")[a is None], str(a)) 
0

首先,我會強烈提醒您不要使用SELECT * FROM tbl WHERE (col = :x OR col IS NULL),因爲這很可能會從資格索引查詢(使用查詢分析器)。 SET ANSI_NULLS也是您的特定數據庫類型可能不支持的那些內容之一。

更好的解決方案(或至少是一個更通用的解決方案),如果你的SQL方言支持Coalesce,寫你的查詢是這樣的:

SELECT * FROM tbl WHERE col = COALESCE(:x, col) 

由於col = col將始終爲true,傳遞NULL對於:x不會損壞您的查詢,並且應該允許更有效的查詢計劃。這也有一個好處,它可以在存儲過程內工作,在那裏你可能沒有動態構建查詢字符串的自由。

0

以下是在python sqlite3上測試的,但它應該可以在其他數據庫類型中使用,因爲它非常通用。這個方法和@MoshiBin的答案一樣,有一些增加:

這裏是使用光標的表單。執行()常規語法,所以在使用這種形式,不支持空變量:

import sqlite3 
conn = sqlite3.connect('mydbfile.db') 
c = conn.cursor() 
c.execute('SELECT * FROM TestTable WHERE colname = ?', (a,)) 

爲了支持空變量,你可以更換4號線:

request = 'SELECT * FROM TestTable WHERE colname %s' % ('= ' + str(a) if a else 'IS NULL') 
c.execute(request) 

另外,如果變量是文本類型,還需要包括引號:

request = "SELECT * FROM TestTable WHERE colname %s" % ("= '" + a + "'" if a else 'IS NULL') 

Finaly如果一個變量可以包含一個單引號本身,還需要加倍逃脫它:

request = "SELECT * FROM TestTable WHERE colname %s" % ("= '" + a.replace("'", "''") + "'" if a else 'IS NULL') 

編輯
最近我發現,也可以在這種情況下使用,使用常規cursor.execute()語法其他兩種方法,但是我現在這個的人我以前不測試:

c.execute('SELECT * FROM TestTable WHERE colname = :1 OR (:1 IS NULL AND colname IS NULL)', {'1': a}) 

(Thx至@BillKarwin answer

,或者使用CASE表達式:

c.execute('SELECT * FROM TestTable WHERE CASE :1 WHEN NOT NULL THEN colname = :1 ELSE colname IS NULL END', {'1': a})