2009-06-30 92 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})