Python SQL Select具有可能的空值
我是python新手,在尝试执行SQL查询时遇到了一个问题 我正在创建一个SQL SELECT语句,该语句由数组中的值填充,如下所示:Python SQL Select具有可能的空值,python,sql,null,Python,Sql,Null,我是python新手,在尝试执行SQL查询时遇到了一个问题 我正在创建一个SQL SELECT语句,该语句由数组中的值填充,如下所示: ret = conn.execute('SELECT * FROM TestTable WHERE a = ? b = ? c = ?', *values) 在值数组中有实值的情况下,这可以正常工作。但是,在某些情况下,值中的单个条目可能设置为“无”。然后查询失败,因为“=NULL”测试不起作用,因为测试应该为NULL 有没有简单的方法解决这个问题?使用:“从
ret = conn.execute('SELECT * FROM TestTable WHERE a = ? b = ? c = ?', *values)
在值数组中有实值的情况下,这可以正常工作。但是,在某些情况下,值中的单个条目可能设置为“无”。然后查询失败,因为“=NULL”测试不起作用,因为测试应该为NULL
有没有简单的方法解决这个问题?使用:“从testtable中选择*,其中(a=?或a为null)和(b=?或b为null)”
这将选择a与提供的值完全匹配的情况,并将在列中包含空值-如果这是您想要的。如果您喜欢冒险,也可以查看SQLAlchemy。它提供了一个SQL构造工具包,可以自动将“无”的比较转换为“为空”的操作。您始终可以使用三元运算符将“=”转换为“为”:
("=","IS")[var is None]
如果var为None,则返回“IS”,否则返回“=”
但在一行中这样做并不十分优雅,只是为了演示:
query = "SELECT * FROM testTable WHERE a %s %s" % ( ("=","IS")[a is None], str(a) )
如果您使用的是SQL Server,那么只要将会话“=null”的ANSI_null设置为off,比较就可以工作
首先,我要强烈警告您不要使用
SELECT*FROM tbl,其中(col=:x或col为NULL)
,因为这很可能会取消您的查询的索引资格(使用查询探查器)SET ANSI_NULLS
也是特定数据库类型中可能不支持的内容之一
如果您的SQL方言支持Coalesce
,那么更好的解决方案(或者至少是更通用的解决方案)是这样编写查询:
SELECT * FROM tbl WHERE col = COALESCE(:x, col)
由于
col=col
的计算结果始终为true,因此将的NULL
传递给:x
不会损坏您的查询,并且应该考虑到更高效的查询计划。这还有一个优点,即它可以在存储过程中工作,在存储过程中,您可能无法自由地动态构建查询字符串。以下内容现在已经在python sqlite3上进行了测试,但是它应该可以在其他DB类型中工作,因为它非常通用。方法与@MoshiBin答案相同,但有一些补充:
以下是使用cursor.execute()常规语法的表单,因此使用此表单时不支持空变量:
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')
最后,如果变量本身可以包含单引号,则还需要通过加倍来转义:
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)
或者,使用大小写表达式:
c.execute('SELECT * FROM TestTable WHERE CASE :1 WHEN NOT NULL THEN colname = :1 ELSE colname IS NULL END', {'1': a})
这对我来说很管用
with mysqlcon.cursor() as cursor:
sql = "SELECT * \
FROM `books` \
WHERE `date` is NULL"
cursor.execute(sql)
books = cursor.fetchall()
return books
另外,Python值None
相当于SQLNULL
。这是一个很好的简单解决方案,运行良好。非常感谢!