【问题标题】:Django seems to be falsely claiming an SQL syntax errorDjango 似乎错误地声称 SQL 语法错误
【发布时间】:2012-02-15 14:44:48
【问题描述】:

Django 似乎错误地声称我的 SQL 语法有错误。查询在 django dbshel​​l 中运行良好(返回预期结果),但在通过 Django 运行查询时会产生错误。下面是代码(回溯如下):

#this code is inside the models.Customer.display_sharers() function
sharers_by_action_count = Sharer.objects.raw('''
SELECT wordout_sharer.id, COUNT(actions_of_type.id) AS action_count
FROM
wordout_customer
INNER JOIN wordout_sharer
 ON wordout_sharer.customer_id = wordout_customer.id
LEFT JOIN wordout_click
 ON wordout_sharer.id = wordout_click.sharer_id
LEFT JOIN
(SELECT wordout_action.id, wordout_action.click_id
FROM wordout_action
WHERE
wordout_action.action_type_id = %s) as actions_of_type
 ON actions_of_type.click_id = wordout_click.id
WHERE wordout_customer.id = %s
GROUP BY wordout_sharer.id
ORDER BY action_count %s
''', (action_type_id, self.id, direction))

force_execution = list(sharers_by_action_count) #force the query to run by converting it to a list.. this is to trigger the error.

这是回溯:

Traceback (most recent call last):
  File "<console>", line 1, in <module>
  File "/Users/me/sources/django_wordout/../django_wordout/wordout/models.py", line 106, in display_sharers
    if order_by == 'action_count': #we have to make a special query for when they want to sort by the count of a specific action
  File "/Users/me/sources/django_wordout/../django_wordout/wordout/models.py", line 92, in sharers_by_action_count_with_total_clicks
    force_exec = list(sharers_by_action_count)
  File "/Library/Python/2.7/site-packages/django/db/models/query.py", line 1324, in __iter__
    query = iter(self.query)
  File "/Library/Python/2.7/site-packages/django/db/models/sql/query.py", line 67, in __iter__
    self._execute_query()
  File "/Library/Python/2.7/site-packages/django/db/models/sql/query.py", line 81, in _execute_query
    self.cursor.execute(self.sql, self.params)
  File "/Library/Python/2.7/site-packages/django/db/backends/util.py", line 34, in execute
    return self.cursor.execute(sql, params)
  File "/Library/Python/2.7/site-packages/django/db/backends/sqlite3/base.py", line 234, in execute
    return Database.Cursor.execute(self, query, params)
DatabaseError: near "?": syntax error

Database.Cursor.execute(self, query, params)执行时,所有参数的值如下:

自我

<django.db.backends.sqlite3.base.SQLiteCursorWrapper object at 0x10c477180> 

查询

        SELECT wordout_sharer.id, COUNT(actions_of_type.id) AS action_count
        FROM
        wordout_customer
        INNER JOIN wordout_sharer
         ON wordout_sharer.customer_id = wordout_customer.id
        LEFT JOIN wordout_click
         ON wordout_sharer.id = wordout_click.sharer_id
        LEFT JOIN
        (SELECT wordout_action.id, wordout_action.click_id
        FROM wordout_action
        WHERE
        wordout_action.action_type_id = ?) as actions_of_type
         ON actions_of_type.click_id = wordout_click.id
        WHERE wordout_customer.id = ?
        GROUP BY wordout_sharer.id
        ORDER BY action_count ?

参数:

         (1, 1, 'DESC')

我是否在 Django 中发现了一个错误?是不是不能正确处理某些类型的查询?

我的配置:我正在运行一个非常普通的开发配置。对于 db 引擎,我使用的是 sqlite。对于迁移(最新的),我使用的是 South。

更新

刚刚发现用它们的值替换 %s 可以使查询正常工作.. 是什么导致 %s 对 Django 产生问题?

【问题讨论】:

  • 您确定您没有在整个问题周围使用一组额外的单引号发送查询吗?从垃圾场看是这样的。
  • 我的代码与我粘贴在代码 sn-p 中的完全一致
  • 啊,但是发现了一些非常有趣的东西——当我不使用%s 并直接发送值时,查询运行良好。可能是什么问题?
  • 我知道您无法在某些数据库上参数化排序顺序,但我不确定 Sqlite,请尝试仅更改该参数。
  • 是的,订单参数化订单是问题所在。如果您可以发布带有相关文档链接的答案(如果存在),我将不胜感激地将其标记为正确

标签: sql django sqlite django-models


【解决方案1】:

我发现自己处于类似的境地。在我们的两种情况下,我们都以正确的方式做事,不使用字符串格式:

Database.Cursor.execute(self, query, params)

但是,如果您绝对信任您的输入(即它们是系统提供的,而不是用户提供的),我发现我可以通过危险的方式绕过此错误:

Database.Cursor.execute(self, query % tuple(params))

致未来的读者:请注意,如果您将其用作解决方法,这会使您容易受到 SQL 注入的攻击。如果您不明白这意味着什么,请不要这样做!

【讨论】:

    【解决方案2】:

    According to this page,sqlite 将参数化值视为文字,这意味着它们插入给定类型的常量,而不是进行常规的“文本替换”。

    由于顺序中的ASC或DESC是关键字,不是常数,所以不能用参数代替。

    这实际上会产生一些可能意想不到的行为,例如,如果你这样做

    ORDER BY ? DESC
    

    你给它一个列名(比如column1),它实际上运行但没有按照你预期的顺序排序。原因是它实际上是按字符串“column1”排序的——每一行都是一样的——而不是实际的列内容。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2023-03-21
      • 2015-06-11
      • 1970-01-01
      • 2018-12-14
      • 2021-09-19
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多