Mysql 参数化Django原始查询产生的结果与非参数化原始查询不同

Mysql 参数化Django原始查询产生的结果与非参数化原始查询不同,mysql,django,django-models,Mysql,Django,Django Models,我正在使用带有两个参数的SQL字符串对Django模型进行原始查询。令人头痛的是,如果我使用字符串替换来填充参数,我会得到比使用参数替换更多的结果。在后一种情况下,结果是正确的,只是不完整。代码如下所示,唯一的变化是我省略了确切的SQL: # I have a long and ornate SQL statement that looks basically like this. sql = "SELECT blah blah WHERE something = %s AND somethin

我正在使用带有两个参数的SQL字符串对Django模型进行原始查询。令人头痛的是,如果我使用字符串替换来填充参数,我会得到比使用参数替换更多的结果。在后一种情况下,结果是正确的,只是不完整。代码如下所示,唯一的变化是我省略了确切的SQL:

# I have a long and ornate SQL statement that looks basically like this.
sql = "SELECT blah blah WHERE something = %s AND something_else in (%s)"

# If I do a raw query with string substitution I get more results (22) ...      
sqlInsecureFilled = sql % (divID, storeRestrictStr)
promos_insecured = Promotions.objects.raw(sqlInsecureFilled)

# ... than if I use a parameterized raw query, which produces (10)
promos_secure = Promotions.objects.raw(sql, [divID, storeRestrictStr])
但它变得更奇怪了。如果我从命令行执行此操作,从原始查询对象(即promos\u secure.query)获取SQL并将其复制到Sequel Pro终端,那么两个查询都会产生相同数量的结果——22!然而:

In [35]: [len(list(promos_insecured)), len(list(promos_secure))]
Out[35]: [22, 10]
总而言之,查询看起来是一样的(相当长,所以很难准确地说出来),当promos_xx.query字符串被复制到MySQL终端时,它们会生成完整的结果集。然而,当如上所示执行时,参数化版本返回10个结果,而另一个版本返回完整的22个结果

为了完整起见,这里是promos_secure.query(promos_unsecured是相同的):


字符串替换的问题是,引用很可能做了一些你意想不到的事情。有些事情可以尝试:

  • 现在,您正在以字符串形式传递ID列表(
    storeRestrictStr
    )。尝试将其作为列表传递

  • 安装并使用它查看正在生成的实际SQL及其输出

  • 你没有说10个结果是否正确,22个结果是否有12个错误匹配,或者22个结果是否正确,10个结果是否缺少12个,或者介于两者之间


22是正确的、完整的。10也正确,但缺少其他12个。如果有一个模式的结果是失踪,这是太微妙的,我发现。我将尝试您的其他建议,但有一个问题:正如我前面所述,转到RawQuerySet对象并获取其“query”属性是否会为您提供实际发出的查询?我没有处理RawQuerySet,但这可能会起作用。我知道有一种机制可以获取实际的查询;DjDT使用它。谢谢你的建议。Django工具栏揭示了一个微妙的差异,现在已经超出了这个问题的范围。如果你好奇,这里有一个新问题:
SELECT DISTINCT promotion_id, promotion_name, promotion_up_date, promotion_down_date, promotion_asset_id, promotion_notes, promotion_promo_id FROM promotions, promo_detail WHERE promotion_id = promo_detail_promotion_id AND promotion_start_date < now() AND promotion_end_date > now() AND promo_detail_cust_division_id = 1 AND promo_detail_not_expired = 1 AND promo_detail_store_id in (8214, 8217, 4952, 8194, 8198, 8162, 5010, 5011, 5012, 8219, 8182, 5048, 5076, 5095, 5096, 5102, 5109, 5131, 5156, 5160, 5161, 5165, 5166, 5173, 5182, 5198, 5200, 5201, 5202, 5203, 5227, 5228, 5229, 5230, 5232, 5233, 5234, <bunch of other comma-separated numbers omitted>, 9281) ORDER BY promotion_end_date ASC
promo_u = promotions.models.Promotions.objects.raw(sql % (1, storeRestrictStr))
promo_s = promotions.models.Promotions.objects.raw(sql, (1, storeRestrictStr))

pid_u = [s.promotion_id for s in promo_u]
pid_s = [s.promotion_id for s in promo_s]

In [76]: [len(list(pid_u)), len(list(pid_s))]
Out[76]: [22, 10]

# You can see the smaller number of results is a subset of the larger.
In [77]: [pid in pid_u for pid in pid_s]
Out[77]: [True, True, True, True, True, True, True, True, True, True]

# The larger number results shows no obvious pattern as to why they're missing.
In [87]: [pid in pid_s for pid in pid_u]
Out[87]: [False, False, False, False, True, False, False, False, True, True, True, True,
          True, False, True, False, False, True, False, True, False, True]