Django MySql原生查询错误 - 参数索引超出范围

1 投票
2 回答
2050 浏览
提问于 2025-04-15 19:10

这个视图在普通的Python/Django/mysql环境下运行得很好。
我正在把它移植到jython/Django/mysql上,但出现了错误。

Exception received is : error setting index [10] [SQLCode: 0]    
Parameter index out of range (10 > number of parameters, which is 0). [SQLCode: 0],  
[SQLState: S1009]

这个查询是 -

cursor.execute("select value from table_name    
where value_till_dt >= str_to_date('%s,%s,%s,%s,%s', '%%m,%%d,%%Y,%%H,%%i')    
AND value_till_dt <=  str_to_date('%s,%s,%s,%s,%s', '%%m,%%d,%%Y,%%H,%%i')    
and granularity='5'    
ORDER BY value_till_dt",    
[int(tempStart.month),int(tempStart.day), int(tempStart.year), int(tempStart.hour), int(tempStart.minute),    
int(tempEnd.month), int(tempEnd.day), int(tempEnd.year), int(tempEnd.hour), int(tempEnd.minute)])

你可以看到,这个查询传入了10个参数。
这个错误是否意味着查询没有接收到这些参数呢?

我在执行之前打印了这些参数,显示它们确实被正确传递了 -

1 - Start Parameters being passed are : 1 11 2010 10 0   
2 - End Parameters being passed are : 1 11 2010 10 5

第二个环境唯一不同的是,这个日期范围内没有可用的数据。但这个错误似乎和数据没有关系。

任何想法都很受欢迎。

2 个回答

0

你确定参数标记是 %s 而不是 ? 或者 :parameter 吗?可以查看一下 DB-API 模块的 paramstyle 参数来确认一下。

2

这确实是一个参数格式的问题。你需要用 ? 来代替 %s。

下面是你如何重现你遇到的错误:

shell> jython
>>> from com.ziclix.python.sql import zxJDBC
>>> (d, v) = "jdbc:mysql://localhost/test", "org.gjt.mm.mysql.Driver"
>>> cnx = zxJDBC.connect(d, None, None, v)
>>> cur = cnx.cursor()
>>> cur.execute("SELECT %s", ('ham',))
..
zxJDBC.Error: error setting index [1] [SQLCode: 0]
Parameter index out of range (1 > number of parameters,
  which is 0). [SQLCode: 0], [SQLState: S1009]

现在,如果你在 ? 符号周围加上引号,你会遇到同样的问题:

>>> cur.execute("SELECT '?'", ('ham',)) 
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
zxJDBC.Error: error setting index [1] [SQLCode: 0]
Parameter index out of range (1 > number of parameters,
  which is 0). [SQLCode: 0], [SQLState: S1009]

关键是不要使用引号,让数据库接口来处理这个问题:

>>> cur.execute("SELECT ?", ('ham',))  
>>> cur.fetchall()
[(u'ham',)]

这是我在代码中会怎么做。你首先要像这样准备好要用在 str_to_date() 函数中的字符串:

start = "%d,%d,%d,%d,%d" % (int(tempStart.month),
  int(tempStart.day), int(tempStart.year),int(tempStart.hour), 
  int(tempStart.minute))
stop = "%d,%d,%d,%d,%d" % (int(tempEnd.month),
  int(tempEnd.day), int(tempEnd.year), int(tempEnd.hour),
  int(tempEnd.minute))

你写出 SELECT 语句,但不要使用任何引号,然后把它传给游标。数据库接口会为你完成这个工作。此外,我们把 'granularity' 的值作为一个参数。

select = """SELECT value FROM table_name
  WHERE value_till_dt >= str_to_date(?, '%%m,%%d,%%Y,%%H,%%i')
  AND value_till_dt <= str_to_date(?, '%%m,%%d,%%Y,%%H,%%i')
  AND granularity=?
  ORDER BY value_till_dt
"""
cursor.execute(select, (start,stop,5))

希望这能帮到你!

撰写回答