所以我在Python中有一堆数组数据。好吧,相反,我有一份清单清单。我正在尝试将此数组存储到MySQL数据库中的单个单元格中。我试图使用JSON来序列化我的数据,但也许我不明白JSON是如何工作的。
所以在连接到我的数据库之后:(我已经为上游和下游尝试了LONGTEXT和LONGBLOB数据类型
cur = con.cursor()
cur.execute("CREATE TABLE IF NOT EXISTS 963168MBV17A(Id INT AUTO_INCREMENT PRIMARY KEY, Rev INT, Part VARCHAR(15), SN INT(7), Date DATE, Time TIME, Iterations INT(3), Upstream LONGBLOB, Downstream LONGBLOB, ResultList LONGTEXT, Result CHAR(1), Report LONGBLOB)")
我获取名为upstream_data和downstream_data的列表列表并执行:
export_upstream = json.dumps(upstream_data)
export_downstream = json.dumps(downstream_data)
然后我执行SQL命令:
cur = con.cursor()
sql_input = "INSERT INTO 963168MBV17A(Rev, Part, SN, Iterations, Date, Time, Upstream, Downstream, ResultList, Result, Report) VALUES('503', '100-120970-0031', '1594539', '%s', '%s', '%s', '%s', '%s', 0, P, 0" %(export_date, export_time, export_numtests, export_upstream, export_downstream)
cur.execute(sql_input)
引用Mordi的答案(http://stackoverflow.com/questions/4251124/inserting-json-into-mysql-using-python),我甚至尝试过:
export_upstream = json.dumps(json.dumps(upstream_data))
export_downstream = json.dumps(json.dumps(downstream_data))
但不管我最终得出错误:
Traceback (most recent call last):
File "P:\Projects\testing database\scrap\test.py", line 83, in <module>
cur.execute(sql_input)
File "C:\Python27\lib\site-packages\MySQLdb\cursors.py", line 174, in execute
self.errorhandler(self, exc, value)
File "C:\Python27\lib\site-packages\MySQLdb\connections.py", line 36, in defaulterrorhandler
raise errorclass, errorvalue
ProgrammingError: (1064, "You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near '' at line 1")
此外,我做的时候
print "about to execute(%s)" % sql_input
我看到JSON对象显示为一个长字符串,其中包含大量单引号(对于列表,在外部表示字符串)。当我执行json.dumps(json.dumps(upstream_data))时,内部引号变成双引号“”并以\ _字符开头。不过,我仍然得到同样的错误。
有什么想法吗?如果没有,有什么更好的方法将Python数组/列表数据存储到单个MySQL单元中?
输出here
答案 0 :(得分:6)
你需要让MySQL库为你做参数处理;这有一个额外的好处,就是让MySQL准备你的语句,也可以更快地重复插入:
cur = con.cursor()
sql_input = "INSERT INTO 963168MBV17A(Rev, Part, SN, Iterations, Date, Time, Upstream, Downstream, ResultList, Result, Report) VALUES('503', '100-120970-0031', '1594539', ?, ?, ?, ?, ?, 0, P, 0"
cur.execute(sql_input, (export_date, export_time, export_numtests, export_upstream, export_downstream))
有关参数化SQL的(某些)更多详细信息,请参阅Python DB API 2.0 spec。每个数据库适配器都记录了确切支持的参数格式,因此也请检查。例如,MySQLdb模块模仿python字符串格式化语法,并使用%s
作为占位符:
sql_input = "INSERT INTO 963168MBV17A(Rev, Part, SN, Iterations, Date, Time, Upstream, Downstream, ResultList, Result, Report) VALUES('503', '100-120970-0031', '1594539', %s, %s, %s, %s, %s, 0, P, 0"
其他可能的参数选项是数字(:1, :2
等),名称(:foo, :bar
)或其他形式的python字符串格式,命名格式说明符:(%(foo)s, %(bar)s
)。< / p>
答案 1 :(得分:1)
您只是以不正确的形式调用数据库API,如果您替换这样的参数,您将负责自行转义数据中的引号和双引号。
这不仅可以为您提供错误(并且幸运的话),因为这也会导致SQL注入的危险攻击。
Python的数据库API从头开始设计,以避免此类攻击的可能性,并通过让cursor.execute
的调用为您进行字符串替换来实现这一点。然后它将为您的字符串添加必要的转义。所以,而不是做:
sql_input = "INSERT INTO 963168MBV17A(Rev, Part, SN, Iterations, Date, Time, Upstream, Downstream, ResultList, Result, Report) VALUES('503', '100-120970-0031', '1594539', '%s', '%s', '%s', '%s', '%s', 0, P, 0" %(export_date, export_time, export_numtests, export_upstream, export_downstream)
cur.execute(sql_input)
待办事项
sql_input = "INSERT INTO 963168MBV17A(Rev, Part, SN, Iterations, Date, Time, Upstream, Downstream, ResultList, Result, Report) VALUES(%s, %s,%s, %s, %s, %s, %s, %s, %s, %s, %s"
cur.execute(sql_input, [503, '100-120970-0031', '1594539', export_date, export_time, export_numtests, export_upstream, export_downstream, 0, "P", 0] )
- 但是,如果您需要SOURCE文件中所有那些疯狂的硬编码数字,而不是自动生成的文件,我敢说你的项目注定要失败。
答案 2 :(得分:1)
我在您的代码中看到的第一个问题是:
sql_input = "INSERT INTO table (column) VALUES('%s');" % ( data )
你永远不应该这样做 - 你正在使用字符串插值,它不能保护你免受SQL注入或格式错误的SQL。
大多数python db apis使用与此类似的占位符语法:
sql = "INSERT INTO table (column) VALUES( %s );"
values = (data,)
cur.execute(sql,values)
请注意,您分别传入语句和值。 API处理转义和格式化。
有些人也允许使用dicts:
sql = "INSERT INTO table (column) VALUES( %(id)s );"
values = { 'id': 1 )
cur.execute(sql,values)
了解如何正确使用数据库API - 这是您最大的问题,并可能导致您的所有其他问题。
答案 3 :(得分:1)
您可能尝试的一件事是使用SQLAlchemy的SQL expression generation来处理所有的转义等等,并且让您避免处理许多安全漏洞(至少在插入SQL数据库等方面) 。它可以参数化查询,而不是像您尝试的那样进行内联字符串插值。
答案 4 :(得分:0)
我预计问题是由于逃避SQL命令,或者说缺少相同的。
从来没有,永远这样做;
cursor.execute("INSERT INTO whatever VALUES (%s)" % "foo")
除了你所看到的问题之外,如果你在那里传递用户输入是不安全的(如果你不知道为什么,请查看“小约翰尼表”)。
相反,这样做:
cursor.execute("INSERT INTO whatever VALUES (%s)", ["foo"])
让MySql接口排除转义。