【发布时间】:2014-03-07 06:38:18
【问题描述】:
目前,我知道如何在 SQL Alchemy 中表达 NULL 安全 != 比较(与 NULL 条目的比较结果为 True,而不是 NULL)的唯一方法是:
or_(field == None, field != value)
有没有办法在 SQL Alchemy 中表达这一点,使其发出 MySQL <=> 操作或 PostgreSQL IS DISTINCT FROM 操作,将 NULL 视为另一个可能的值?
附加上下文
这是从基于 XML 的查询语言转换为 SQL Alchemy 过滤器表达式的实用程序中的一个错误:http://gerrit.beaker-project.org/#/c/2776/
具体的错误出现在如下所示的 sn-p 代码中:
query = getattr(field, op)(value)
其中“field”是相关的 SQL Alchemy 模型列,“op”是用于比较操作的相关 Python 属性名称,“value”是要检查的值。例如,在过滤运行在具有特定名称的虚拟机管理程序上的虚拟机的特定情况下,它相当于这样做:
query = Hypervisor.hypervisor.__eq__("KVM")
错误的出现不是由于 value 可能是 NULL(这不会发生 - 值始终是字符串),而是在与 列 所在的行进行比较时em> 包含一个NULL 值,比较运算符是__ne__。
对于除__ne__ 之外的每个运算符,标准SQL NULL 处理工作正常(比较返回NULL,这被解释为与过滤器不匹配的行,这是我们想要的)。但是,对于__ne__ 的情况,我们确实希望返回该列中包含 NULL 值的行 - 我们只想排除设置了值的行并且 em> 它与我们要比较的值不匹配。
原来的代码是这样的:
query = getattr(field, op)(value)
现在看起来更像:
if op == "__ne__":
query = or_(field == None, field != value)
else:
query = getattr(field, op)(value)
这对我来说似乎很笨拙,所以我想问是否有一种方法可以将“!=”映射到 __ne__ 以外的其他位置,这将为我们提供在数据库层处理而不是模拟它的备用 NULL使用相当于field IS NOT NULL OR field != value 的 SQL Alchemy(我们现在已经开始这样做了)。
【问题讨论】:
-
IFNULL(field, '')或类似将任何空值转换为空字符串? -
有不同的方法可以解决这个问题,您可以实现一个输出
<=>/IS DISTINCT FROM的运算符,或者您可以创建一个输出or_()的运算符。但是,如果不做出一些让步,他们都不会做的是能够将“None”作为绑定值处理,也就是说,如果您输入 None 与 non-None(假设绑定值为非无)。这通常不是问题(例如x IS NOT NULL与x != %(value)s),但如果这是类似 executemany() 类型的事情,那么它可能是。 -
但我不太确定你想要什么。如果您传入“None”或一个值(根据该值呈现运算符),核心表达式 - > SQL 映射已经生成了一个不可知的表达式,所以看起来您可能正在寻找一些固定在 SQL 上的东西边。我必须对您使用的 DBAPI 进行试验,看看如果您将“无”作为绑定值会发生什么。
-
添加了更多关于我们正在做的事情的上下文 - 它是一个数据驱动的过滤器生成器,具体的问题是我们目前必须使用特殊情况
__ne__才能获得带有 a 的行的正确答案NULL在相关栏中。如果我们能以某种方式将其映射到不同的数据库操作符,我们或许可以移除当前的特殊情况,而只需更改操作 -> 方法名称映射。
标签: python sqlalchemy