2012-04-19 8 views
1

Я строю строку запроса.Python TypeError при построении строки запроса

query = "SELECT seqid, date, name, steamid, team, text, type, '%s' as triggerword, '%s' as weight FROM chatlogs WHERE date > '%s' AND text LIKE '%%%s%%' ORDER BY DATE" % (word, weight, self.setting['LAST_RUN_TIME'], word) 

Если напечатать строку, она возвращает правильно:

SELECT seqid, date, name, steamid, team, text, type, 'hunting_term' as triggerword, '0.01' as weight FROM chatlogs WHERE date > '2012-04-18 23:47:58.439124' AND text LIKE '%hunting_term%' ORDER BY DATE 

Тем не менее, после этого терпеть неудачу с исключением TypeError: TypeError: не хватает аргументов для строки формата

Полный код:

import database 

mysqldb = database.Connection('localhost','mydb',user='myuser',password='mypass') 

word = 'hunting_term' 
weight = 0.01 
setting = dict({'LAST_RUN_TIME':'2012-04-18 23:47:58.439124'}) 

query = "SELECT seqid, date, name, steamid, team, text, type, '%s' as triggerword, '%s' as weight FROM chatlogs WHERE date > '%s' AND text LIKE '%%%s%%' ORDER BY DATE" % (word, weight, setting['LAST_RUN_TIME'], word) 
print query 

for message in mysqldb.query(query):  # This is the line it throws the exception on 
    print "A row" 

база данных от tornado пакет

+1

Что произойдет, если вы измените '«%%% сек %%»' для ' '%%%%% сек %%%%' '? –

ответ

5

Проблема здесь в том, что в конечном итоге вызов MySQLdb выглядит примерно так:

query = "SELECT seqid, date, name, steamid, team, text, type, 'hunting_term' as triggerword, '0.01' as weight FROM chatlogs WHERE date > '2012-04-18 23:47:58.439124' AND text LIKE '%hunting_term%' ORDER BY DATE" 
db.cursor().execute(query,()) 

Первый аргумент db.cursor().execute() должен быть строкой формата, а второй аргумент должен быть заменой для этого формата string, вы можете увидеть это в MySQLdb docs. Другими словами, он будет выполнять следующий код:

query %() 

Как вы можете видеть, это приведет к тому же TypeError:

>>> query %() 
Traceback (most recent call last): 
    File "<stdin>", line 1, in <module> 
TypeError: not enough arguments for format string 

Это означает, что любой литерал %, что вы хотите MySQL видеть потребности в быть %%, когда она рассматривается db.cursor().execute(), так что вы должны быть в состоянии это исправить, изменив исходную строку формата к следующему:

query = "SELECT seqid, date, name, steamid, team, text, type, '%s' as triggerword, '%s' as weight FROM chatlogs WHERE date > '%s' AND text LIKE '%%%%%s%%%%' ORDER BY DATE" % (word, weight, self.setting['LAST_RUN_TIME'], word) 

Однако правильный способ сделать это, чтобы позволить MySQLdb выполнять замены для вас, что бы изменить свой код на следующее:

query = "SELECT seqid, date, name, steamid, team, text, type, %s as triggerword, %s as weight FROM chatlogs WHERE date > %s AND text LIKE %s ORDER BY DATE" 
parameters = (word, weight, setting['LAST_RUN_TIME'], '%%%s%%' % word) 
for message in mysqldb.query(query, *parameters): 
    print "A row" 
+0

Предоставление MySQLdb выполнения замен для вас предпочтительнее, потому что оно защитит от SQL-инъекции. –

+0

@StevenRumbalski, если это так, как MySQLdb выполняет подстановки, то это приглашение на SQL-инъекцию, а не защиту от него. –

+1

@MarkRansom, фактически позволяя MySQLdb делать это за вас, является более безопасным, поскольку он выполняет все необходимые экранирование, чтобы убедиться, что '% s' всегда становится единственным значением. Я упростил то, что происходит на стороне MySQLdb, это сложнее, чем 'query% parameters'. –

Смежные вопросы