1

在我的 Django 应用程序中,我需要像这样生成一个 MySQL 查询:

SELECT * FROM player WHERE (myapp_player.sport_id = 4 AND (myapp_player.last_name LIKE 'smi%'))
UNION
SELECT * FROM player WHERE (myapp_player.sport_id = 4 AND (myapp_player.first_name LIKE 'smi%'));

我不能使用 Q 对象来 OR 一起 __istartswith 过滤器,因为 Django ORM 生成的查询不使用 UNION 并且它的运行速度至少比上面的 UNION 查询慢 40 倍。对于我的应用程序,这种性能是不可接受的。

所以我正在尝试这样的东西:

Player.objects.raw("SELECT * FROM myapp_player WHERE (sport_id = %%s AND (last_name LIKE '%%s%')) UNION SELECT * FROM sports_player WHERE (sport_id = %%s AND (first_name LIKE '%%s%'))", (sport.id, qword, sport.id, qword))

我为冗长的单行表示歉意,但我想在尝试调试此类问题时避免使用三引号字符串。

当我执行或 repr 这个查询集对象时,我得到如下异常:

*** ValueError: unsupported format character ''' (0x27) at index 133

那是单引号中的单引号,而不是三引号。如果我去掉 LIKE 子句周围的单引号,那么我会得到关于 LIKE 子句后面的 close-paren ) 字符的类似异常。

显然 Django 和 MySQL 不同意这个查询的正确语法,但有没有一种语法对两者都适用?

最后,我也不确定用于字符串插值的 %%s 语法是否正确。Django 文档建议我应该能够在 raw() 的参数中使用常规的 %s 语法,但是一些在线资源建议使用 %%s 或 ? 作为原始 SQL 中字符串插值的占位符。

我真诚地感谢您对这个问题的一点点澄清!

4

1 回答 1

3

我让它像这样工作:

qword = word + '%'
Player.objects.raw("SELECT * FROM myapp_player WHERE (sport_id = %s AND (last_name LIKE %s)) UNION SELECT * FROM myapp_player WHERE (sport_id = %s AND (first_name LIKE %s))", (sport.id, qword, sport.id, qword))

除了 %s 似乎是参数化原始查询的正确方法这一事实之外,这里的关键是在调用 raw() 之前将 % 通配符添加到 LIKE 子句,并从 LIKE 子句周围排除单引号。即使 LIKE 子句周围没有引号,引号也会出现在最终发送到 MySQL 服务器的查询中。

于 2013-06-05T19:59:17.180 回答