将 Python 列表(JSON 或其他)插入 MySQL 数据库
Posted
技术标签:
【中文标题】将 Python 列表(JSON 或其他)插入 MySQL 数据库【英文标题】:Insert Python List (JSON or otherwise) into MySQL databse 【发布时间】:2012-08-31 14:02:03 【问题描述】:所以我在 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://***.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
【问题讨论】:
【参考方案1】:您可能会尝试的一件事是使用 SQLAlchemy 的SQL expression generation,它将为您处理所有转义等问题,另外还可以让您避免处理许多安全漏洞(至少在插入 SQL 数据库等方面)。它参数化查询,而不是像您尝试做的那样进行内联字符串插值。
【讨论】:
【参考方案2】:你需要让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))
请参阅Python DB API 2.0 spec 了解有关参数化 SQL 的(一些)更多详细信息。每个数据库适配器都记录了确切支持的参数格式,因此也要检查一下。例如,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
)。
【讨论】:
谢谢,这完全有帮助。我选择 jsbueno 的答案作为已接受的答案,因为在 sql_input 中插入了一些参数,而在执行命令期间传入了其他参数,这对我来说会导致 TypeError(TypeError:并非所有参数都在字符串格式化期间转换)。但是,再次感谢,这绝对为我指明了正确的方向。 这听起来像是参数数量和你传入的值不匹配。【参考方案3】:我在您的代码中看到的第一个问题是:
sql_input = "INSERT INTO table (column) VALUES('%s');" % ( data )
你永远不应该这样做——你正在使用字符串插值,它不能保护你免受 SQLinjection 或格式错误的 sql 的影响。
大多数 python db api 使用类似于此的占位符语法:
sql = "INSERT INTO table (column) VALUES( %s );"
values = (data,)
cur.execute(sql,values)
请注意,您分别传入语句和值。 API 处理转义和格式化。
有些也允许使用字典:
sql = "INSERT INTO table (column) VALUES( %(id)s );"
values = 'id': 1 )
cur.execute(sql,values)
阅读如何正确使用您的数据库 api - 这是您最大的问题,并且可能会导致您的所有其他问题。
【讨论】:
【参考方案4】:您只是以错误的形式调用 DB 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 文件中而不是在自动生成的文件中使用所有这些疯狂的硬编码数字,我敢说您的项目无论如何都注定要失败。
【讨论】:
【参考方案5】:我预计问题是由于转义 SQL 命令,或者更确切地说是缺少相同的命令。
永远、永远、永远不要这样做;
cursor.execute("INSERT INTO whatever VALUES (%s)" % "foo")
除了您看到的问题之外,如果您在那里传递用户输入是不安全的(如果您不知道原因,请查看“Little Johnny Tables”)。
相反,这样做:
cursor.execute("INSERT INTO whatever VALUES (%s)", ["foo"])
并让MySql接口整理转义。
【讨论】:
以上是关于将 Python 列表(JSON 或其他)插入 MySQL 数据库的主要内容,如果未能解决你的问题,请参考以下文章
如何优化使用 PHP 或 Mysql 或 Laravel 将 12K 的 JSON 插入数据库
如何在android中将arraylist或vector插入SQLite数据库?