【问题标题】:Calling DATE_FORMAT() in MySQL from Django fails从 Django 调用 MySQL 中的 DATE_FORMAT() 失败
【发布时间】:2013-08-10 19:00:16
【问题描述】:

我可以运行SET 语句来分配变量并在mySQL 会话中使用“事务”来维护它,但是当我像这样包含函数DATE_FORMAT 时:

cursor.execute("SET @dowToday:=CAST( DATE_FORMAT( NOW(), '%w' ) AS UNSIGNED);")

Django 抱怨

在执行中,/usr/lib/pymodules/python2.6/MySQLdb/cursors.py 中的格式字符串参数不足,第 151 行

删除 CAST 或使用或转义引号都无济于事。

想法?

【问题讨论】:

  • 我猜这是 SQL 文本中的% 百分号。也许 Django 期望这是绑定变量占位符。要么,要么 Django 正在运行一些 sprintf 风格的函数,并期望 %w 是一个应该被一些参数值替换的占位符。也许有一种方法可以“转义”%,以便 Django 忽略它,并将其作为文字传递给 MySQL。 (我没有测试过,这真的只是一个猜测。)

标签: mysql django mysql-python


【解决方案1】:

我的猜测是问题出在查询文本中的百分号 (%) 上。 (这不是 Django 中的绑定变量占位符吗?)例如如果我们要使用绑定变量,会不会看起来像这样?

SELECT 'foo' FROM DUAL WHERE 'a' = %(varname)s ;

我想也许 Django 正在扫描您的 SQL 文本并遇到 %w 并期望它是一个绑定变量。要么是这样,要么它正在运行 sprintf 样式函数,遇到 %w 并期望用参数值替换该占位符。

(我没有测试过;所以这只是一个想法,只是一个猜测。)

作为一种解决方法的猜测,也许你将百分号加倍,我们通过 sprintf 得到 % 文字:

  query("SELECT ... ,'%%w') ...");

如果这不起作用,那么它可能是一个反斜杠字符,就像我们在正则表达式中转义字符一样:

  query("SELECT ... ,'\%w') ...");

(或者,您可能需要将反斜杠加倍。这些只是基于其他软件使用的约定的猜测。)

【讨论】:

  • 我没有解决方法,我只是猜测。但是我正在寻找一种方法来“逃避”'%',以便 Django 忽略它(可能将百分比加倍%% sprintf 样式,或者使用反斜杠\%?(仅基于对约定的经验)由其他软件使用)。要么,要么我正在寻找一种方法来禁用 Django 扫描占位符(sqlplus 样式 SET SCAN OFF)。在解决方法方面对我没有太大帮助。对不起。跨度>
  • 第二个答案建议将 % 符号 %% 加倍以使 % 文字通过。 http://stackoverflow.com/questions/4770620/django-raw-query-percent-sign-problem(我看不出选择的问题答案对 Django 有何帮助......或者两者都可以工作。(foo LIKE '\%' 是我们如何让 MySQL 匹配文字 %,对于 MySQL不要将 % 解释为通配符匹配。但这并没有解决让文字百分号滑过 Django 的问题。
【解决方案2】:

我完全错过了我之前回答的重点。这是一个 Django 游标。不是“标准 Python”。

根据文档:

https://docs.djangoproject.com/en/dev/topics/db/sql/

请注意,如果您想在查询中包含文字百分号, 如果您传递参数,则必须将它们加倍:

cursor.execute("SELECT foo FROM bar WHERE baz = '30%%' and id = %s", [self.id])

我假设如果这不起作用,您可以回退到一些简单而愚蠢的技巧:

cursor.execute("SET @dowToday:=CAST( DATE_FORMAT( NOW(), '%sw' ) AS UNSIGNED);", ['%'])

%s 将替换为作为参数传递的%...

【讨论】:

  • 谢谢,虽然使用 %s 或 \% 不起作用,但使用双百分比解决了它。 cursor.execute("SET @dowToday:=CAST( DATE_FORMAT( NOW(), '%%w' ) AS UNSIGNED);")
  • @IMStarboard ...嗯...我很失望那个“%s”技巧没有奏效:(无论如何,%% 是推荐的方式,它很棒它对你有用:D
【解决方案3】:

您确定错误是由 that 调用产生的吗?


查看我系统上cursor.py 的代码,导致:

def execute(self, query, args=None):

    # ...

    if isinstance(query, unicode):
        query = query.encode(charset)
    if args is not None:
        query = query % db.literal(args)         # Line 151

据此,只有在 args 不是 None 时才会引发此异常——考虑到调用,这似乎是不可能的:

cursor.execute("SET @dowToday:=CAST( DATE_FORMAT( NOW(), '%w' ) AS UNSIGNED);")

【讨论】:

  • 我知道这看起来很疯狂,但这是另一个引发相同错误的示例: cursor.execute("SELECT DATE_FORMAT( created_at, '%w' ) FROM Discussion_posts limit 2")
  • 还应该提到,如果我用不包含 DATE_FORMAT 函数的不同语句替换那一行,它会起作用
猜你喜欢
  • 1970-01-01
  • 2012-01-30
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-03-23
  • 2011-04-05
  • 2018-11-12
  • 1970-01-01
相关资源
最近更新 更多