2016-06-16 2 views
0

я могу запустить следующий SQL в моем мой-клиента SQL и возвращает правильный результат:Как выполнить оператор mysql в моем коде python?

mysql> select cj.name job_name , cb.build_result build_result, count(*) total , GROUP_CONCAT(cb.id) id_list 
     from ci_build as cb INNER JOIN ci_job as cj 
     ON cb.job_id = cj.id 
     where cb.build_time > date_format('2016-04-16','%Y%m%d') 
     and cb.build_time < date_format('2016-05-27','%Y%m%d') 
     GROUP BY cj.name , cb.build_result; 

enter image description here

Но если я использую следующий код питона, он будет возвращать ошибки:

ValueError: неподдерживаемый формат символ «Y» (0x59) с индексом 225

Любой может помочь то, что случилось с моим питоном кода? Большое спасибо ~

start_time = '2016-04-16' 
end_time = '2016-05-27' 

db = MySQLdb.connect(host='xxxx',port=3306,user='xxxx', passwd='xxxx', db='xxxx',charset='utf8') 

sql_query = "select cj.name job_name , cb.build_result build_result, count(*) total , GROUP_CONCAT(cb.id) id_list from ci_build as cb INNER JOIN ci_job as cj ON cb.job_id = cj.id where cb.build_time > date_format(%s,'%Y%m%d') and cb.build_time < date_format(%s,'%Y%m%d') GROUP BY cj.name , cb.build_result; % (start_time , end_time) 

cursor = db.cursor() 
cursor.execute(sql_query) 
all_res=cursor.fetchall() 
cursor.close() 
db.close() 
+2

В запросе нет закрывающего '' '. Можете ли вы исправить это первое –

ответ

2

Вы используете строку интерполяции для замены %s в ваших двух date_format() с, однако, поскольку % является специальным символом wrt для строковой интерполяции, Python считает, что %Y также является операцией форматирования строк, но это Y не является допустимым спецификатором формата.

Вы можете избежать других % символов путем удвоения вверх % в строке запроса:

date_format('%s','%%Y%%m%%d') 

Вы также должны процитировать %s, так как вы отправляете строку.

Однако я бы рекомендовал использовать параметризованные запросы, а не так как это помогает избежать возможных проблем инъекций SQL:

sql_query = "select cj.name job_name , cb.build_result build_result, count(*) total , GROUP_CONCAT(cb.id) id_list from ci_build as cb INNER JOIN ci_job as cj ON cb.job_id = cj.id where cb.build_time > date_format(%s,'%%Y%%m%%d') and cb.build_time < date_format(%s,'%%Y%%m%%d') GROUP BY cj.name , cb.build_result" 

cursor = db.cursor() 
cursor.execute(sql_query, (start_time , end_time)) 

Это помищения аргументы запроса в виде отдельного кортежа, который передается в cursor.execute(). Механизм базы данных будет безопасно выполнять подстановку, гарантируя, что кавычки и другие специальные символы будут правильно экранированы. Обратите внимание, что здесь не следует указывать местозаполнитель (%s) - двигатель сделает это за вас.

+0

спасибо mhawke за вашу любезную помощь и подробное объяснение, многому научились :) – JiangLing

0

Вы должны удвоить процентные знаки, которые вы не хотите, чтобы интерполировать с argumewnts оператора % и некоторые вещи в дополнение ;-)

sql_query = "select cj.name job_name , cb.build_result build_result, count(*) total , GROUP_CONCAT(cb.id) id_list from ci_build as cb INNER JOIN ci_job as cj ON cb.job_id = cj.id where cb.build_time > date_format('%s','%%Y%%m%%d') and cb.build_time < date_format('%s','%%Y%%m%%d') GROUP BY cj.name , cb.build_result;" % ('a', 'b') 

будет работать. Извините за использование строковых литералов 'a', 'b' для тестирования. Разумеется, вы должны ввести переменные.

Также обратите внимание на добавленную закрывающуюся двойную кавычку после точки с запятой, чтобы положить конец строки (как отмечает @MosesKoledoye), и когда база данных получит заполненную строку, было бы неплохо добавить '%%s', чтобы обернуть вставленный литерал, начинать и заканчивать " times "(но не двойные кавычки, которые, как мне кажется, @sparkandshine) отметили, так как это будет« больше »действительный SQL.

As @mhawke notes: Попробуйте не строить строку запроса sql, впрыскивая материал из переменных!

В один прекрасный день вы контролируете свой контент, и все хорошо, на следующий день вы реорганизуете код и получаете переменные «извне», а SQL-инъекция готова к работе - попробуйте подготовленные операторы для всех сложных запросов (чтобы предложить ДБ возможность оптимизировать уже в PREPARE фазе и добавить многоуровневую безопасность автоматически, имея лучшую защиту в BIND фазы отвергая попытки впрыска на ВЫПОЛНИТЬ время фазы.

+0

, также спасибо Dilettant, эта проблема беспокоила меня в течение длительного времени, теперь я лучше понимаю, спасибо – JiangLing