【问题标题】:Raw query must include the primary key原始查询必须包含主键
【发布时间】:2013-06-27 15:38:26
【问题描述】:

我的 views.py 中有一条原始 SQL 语句

Message.objects.raw('''
        SELECT s1.ID, s1.CHARACTER_ID, MAX(s1.MESSAGE) MESSAGE, MAX(s1.c) occurrences
        FROM
           (SELECT ID, CHARACTER_ID, MESSAGE, COUNT(*) c
            FROM tbl_message WHERE ts > DATE_SUB(NOW(), INTERVAL %s DAY) GROUP BY CHARACTER_ID,MESSAGE) s1
        LEFT JOIN
           (SELECT ID, CHARACTER_ID, MESSAGE, COUNT(*) c
            FROM tbl_message WHERE ts > DATE_SUB(NOW(), INTERVAL %s DAY) GROUP BY CHARACTER_ID,MESSAGE) s2
          ON s1.CHARACTER_ID=s2.CHARACTER_ID
         AND s1.c < s2.c
        WHERE s2.c IS NULL
        GROUP BY CHARACTER_ID
        ORDER BY occurrences DESC''', [days, days])

这条SQL语句的结果(直接在数据库上测试)是:

ID  | CHARACTER_ID | MESSAGE | OCCURENCES
----+--------------+---------+--------------
148 | 10           | test    | 133

但我得到的只是InvalidQuery 异常信息Raw query must include the primary key

然后我仔细检查了docs 并阅读:

只有一个字段不能省略 - 主键 field....如果您忘记包含主键,则会引发 InvalidQuery 异常。

如您所见,我在语句中添加了请求的主键。怎么了?

class Message(models.Model):
    character = models.ForeignKey('Character')
    message = models.TextField()
    location = models.ForeignKey('Location')
    ts = models.DateTimeField()

    class Meta:
        pass

    def __unicode__(self):
        return u'%s: %s...' % (self.character, self.message[0:20])

【问题讨论】:

  • 你还有这个问题吗?
  • 我用一个视图做了一个解决方法......但如果你有解决方案,请随时发布。
  • 你能发布你的Message 模型吗?
  • 解决方法是什么?我正处于你的确切情况。区分大小写并不能解决我的问题。

标签: django django-models


【解决方案1】:

在查询中包含 1 作为 id

Message.objects.raw('''
        SELECT 1 as id , s1.ID, s1.CHARACTER_ID, MAX(s1.MESSAGE) MESSAGE, MAX(s1.c) occurrences
        FROM
           (SELECT ID, CHARACTER_ID, MESSAGE, COUNT(*) c
            FROM tbl_message WHERE ts > DATE_SUB(NOW(), INTERVAL %s DAY) GROUP BY CHARACTER_ID,MESSAGE) s1
        LEFT JOIN
           (SELECT ID, CHARACTER_ID, MESSAGE, COUNT(*) c
            FROM tbl_message WHERE ts > DATE_SUB(NOW(), INTERVAL %s DAY) GROUP BY CHARACTER_ID,MESSAGE) s2
          ON s1.CHARACTER_ID=s2.CHARACTER_ID
         AND s1.c < s2.c
        WHERE s2.c IS NULL
        GROUP BY CHARACTER_ID
        ORDER BY occurrences DESC''', [days, days]) 

【讨论】:

  • 这很有用,因为它还可以防止当您分组并希望忽略 id 字段时出现问题。
【解决方案2】:

我使用 Python 2.7.5、Django 1.5.1 和 Mysql 5.5 重现了同样的问题。

我已将raw 调用的结果保存到results 变量中,因此我可以检查它包含哪些列:

>>> results.columns
['ID', 'CHARACTER_ID', 'MESSAGE', 'occurrences']

ID 是大写的,所以在您的查询中我将s1.ID 更改为s1.id 并且它可以工作:

>>> results = Message.objects.raw('''
...         SELECT s1.id, s1.CHARACTER_ID, MAX(s1.MESSAGE) MESSAGE, MAX(s1.c) occurrences
...         FROM
...            (SELECT ID, CHARACTER_ID, MESSAGE, COUNT(*) c
...             FROM tbl_message WHERE ts > DATE_SUB(NOW(), INTERVAL %s DAY) GROUP BY CHARACTER_ID,MESSAGE) s1
...         LEFT JOIN
...            (SELECT ID, CHARACTER_ID, MESSAGE, COUNT(*) c
...             FROM tbl_message WHERE ts > DATE_SUB(NOW(), INTERVAL %s DAY) GROUP BY CHARACTER_ID,MESSAGE) s2
...           ON s1.CHARACTER_ID=s2.CHARACTER_ID
...          AND s1.c < s2.c
...         WHERE s2.c IS NULL
...         GROUP BY CHARACTER_ID
...         ORDER BY occurrences DESC''', [days, days])
>>> results.columns
['id', 'CHARACTER_ID', 'MESSAGE', 'occurrences']
>>> results[0]
<Message_Deferred_character_id_location_id_message_ts: Character object: hello...>

【讨论】:

    【解决方案3】:

    确保主键是 select 语句的一部分。

    例子:

    这不起作用:

    `Model.objects.raw("Select Min(id), rider_id from Table_Name group by rider_id")`
    

    但这会起作用:

    `Model.objects.raw("Select id, Min(id), rider_id from Table_Name group by rider_id")`
    

    【讨论】:

      【解决方案4】:

      对于那些也遇到这个问题的人,也许像我一样,想知道为什么 Django 需要一个 pk,而当你没有 pk 用于查询时(例如,你想要多行)——Django 只需要一个 @返回 987654323@ 字段,pk 不需要是 where 子句的一部分。即:

      select * from table where foo = 'bar';

      或

      select id, description from table where foo = 'bar';

      如果表中有id 字段,这两种方法都有效。但这会引发 Thomas Schwärzl 描述的错误,因为没有返回 id 字段:

      select description from table where foo = 'bar';

      【讨论】:

        猜你喜欢
        • 2021-10-30
        • 2014-01-21
        • 2020-05-09
        • 2021-02-19
        • 1970-01-01
        • 1970-01-01
        • 2017-06-29
        • 2018-11-14
        • 1970-01-01
        相关资源
        最近更新 更多