如何在我的 python 代码中执行 mysql 语句?
How to execute the mysql statement in my python code?
我可以在我的 sql 客户端中 运行 以下 sql 和 return 正确的结果 :
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;
但是如果我使用下面的 python 代码,它将 return 错误:
ValueError:索引 225
处的格式字符 'Y' (0x59) 不受支持
任何人都可以帮助我的 python 代码出了什么问题?非常感谢~
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()
您必须将不想插值的百分号与 %
运算符的参数和其他一些内容加倍 ;-)
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)指出,因为这将是 "More" 有效 SQL.
正如@mhawke 所指出的:尽量不要通过从变量!
注入内容来构建sql 查询字符串
有一天你控制了它们的内容,一切都很好,第二天你重构了代码,并收到变量 "from the outside" 和 SQL 注入准备好滚动 - 尝试为所有准备好的语句复杂查询(为数据库提供在 PREPARE 阶段优化的可能性,并通过在 BIND 阶段提供更好的保护来自动添加分层安全性,拒绝在 EXECUTE 阶段时间的注入尝试。
您正在使用字符串插值替换两个 date_format()
中的 %s
,但是,由于 %
是字符串插值的特殊字符,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
) - 引擎会为您完成。
我可以在我的 sql 客户端中 运行 以下 sql 和 return 正确的结果 :
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;
但是如果我使用下面的 python 代码,它将 return 错误:
ValueError:索引 225
处的格式字符 'Y' (0x59) 不受支持任何人都可以帮助我的 python 代码出了什么问题?非常感谢~
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()
您必须将不想插值的百分号与 %
运算符的参数和其他一些内容加倍 ;-)
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)指出,因为这将是 "More" 有效 SQL.
正如@mhawke 所指出的:尽量不要通过从变量!
注入内容来构建sql 查询字符串有一天你控制了它们的内容,一切都很好,第二天你重构了代码,并收到变量 "from the outside" 和 SQL 注入准备好滚动 - 尝试为所有准备好的语句复杂查询(为数据库提供在 PREPARE 阶段优化的可能性,并通过在 BIND 阶段提供更好的保护来自动添加分层安全性,拒绝在 EXECUTE 阶段时间的注入尝试。
您正在使用字符串插值替换两个 date_format()
中的 %s
,但是,由于 %
是字符串插值的特殊字符,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
) - 引擎会为您完成。