我正在使用MySQLdb将大量数据从文本文件上传到MySQL服务器。如果我手动准备一个像'as', '123', 12, 23
这样的字符串,这样可以正常工作,但我无法弄清楚如何循环遍历列表来生成这个,因为我需要连接字符串和整数。
有效的insert语句示例如下:
""" INSERT INTO ACS(ST, CODE, BC001, BC002, BC003)
VALUES ('AK', '1234567', 20, 30, 40)"""
这就是我尝试从列表中生成此语句的方式:
import MySQLdb
# sample data
table = 'TestTable'
header = ['ST', 'CODE', 'BC001', 'BC002', 'BC003']
values = [['AA', '1234567', 20, 30, 40], ['BB', '1234567', 20, 30, 40], ['CC', '1234567', 20, 30, 40],['DD', '1234567', 20, 30, 40]]
# local SQL server on my computer
db = MySQLdb.connect (host = 'localhost', user = 'root', passwd = '', db = 'test')
# prepare a cursor object using cursor() method
cursor = db.cursor()
# header columns
sql1 = '('
for i in range(len(header)):
sql1 += header[i] + ','
sql1 = 'INSERT INTO ' + table + sql1[:-1] + ')'
# now loop through data values and combine with header each time
for i in range(len(values)):
sql2 = ''
for j in range(len(values[i])):
sql2 += values[i][j] + ',' #error occurs here
# structure: sql2 = """ VALUES ('AA', '1234567', 20, 30, 40)"""
sql2 = 'VALUES ' + table + sql2[:-1] + ')'
sql = sql1 + sql2
try:
# Execute the SQL command
cursor.execute(sql)
# Commit your changes in the database
db.commit()
except:
# Rollback in case there is any error
db.rollback()
# disconnect from server
db.close()
我收到的错误消息是
TypeError: unsupported operand type(s) for +: 'int' and 'str'
并且我理解为什么会发生这种情况,但我无法找出生成字符串的替代方法。是否有更好的方法来制作这些琴弦?
我在Win7 64位上使用Python27。
答案 0 :(得分:5)
MySQLdb已经可以在不必手动输入变量的情况下执行此操作。
你想这样做因为MySQLdb会在某种程度上自动引用内容并防止SQL注入攻击。这在任何实际环境中都非常重要,如果您打算从事任何专业数据库工作,您应该习惯这一点。
使用MySQLdb游标对象,execute()
命令将自动格式化您的整数,字符串和其他变量,以便它们可以在INSERT
语句中使用。他们使用一种特殊的格式字符串来做到这一点。
c=db.cursor()
max_price = 5
min_price = 1
c.execute("""SELECT spam, eggs, sausage FROM breakfast
WHERE price < %s AND price > %s""", (max_price, min_price))
注意两件事:首先,所有变量,无论类型如何,都应该在这些特殊格式字符串中表示为%s
。这就是它的工作方式。其次,execute()
的第二个参数应该是元组,因此如果您只使用一个变量,则需要键入(max_price,)
。括号末尾的逗号告诉python它是一个元组。
答案 1 :(得分:1)
您是否曾尝试将values[i][j]
简单地包裹在str()
str(values[i][j])
中?
看起来你也可以
sql2 = ','.join([str(x) for x in values[i]]) + ','
如果你想进一步简化它。 (不确定是否有必要使用尾随逗号,但我将其包括在内以匹配您的代码。)
示例:
>>> my_list = ['abc', 1, 2,3, 'do','re','mi']
>>> [str(x) for x in my_list]
['abc', '1', '2', '3', 'do', 're', 'mi']
>>> ','.join([str(x) for x in my_list])
'abc,1,2,3,do,re,mi'
另一方面,如果您需要在最终查询中将原始字符串包装在单引号中的对象(您看起来像这样),则可能需要执行更复杂的操作,例如
sql2 = ''
for x in values[i]:
if isinstance(x, basestring):
sql2 += "'"+x+"',"
else:
sql2 += str(x) +","
答案 2 :(得分:1)
其他帖子正确识别了错误,但没有回答您关于更好地进行字符串格式化的问题。
我不确定这会根据您的需要进行格式化,因为您的代码有点难以阅读。您最终会得到以下查询:
INSERT INTO TestTable (ST,CODE,BC001,BC002,BC003) VALUES ('AA','1234567',20,30,40)
以下是代码:
sql = (('INSERT INTO {0} ({1}) VALUES ({2})'.format(table, ','.join(header),
','.join(("'" + v + "'" if isinstance(v, str)
else str(v)) for v in val))) for val in values)
然后你就做了:
for q in sql:
try:
# Execute the SQL command
cursor.execute(q)
# Commit your changes in the database
db.commit()
except:
# Rollback in case there is any error
db.rollback()
它会为字符串添加引号,并使用str.join
和str.format
。
实际上,您应该使用参数化查询,该查询将值放入字符串中,以推送到数据库连接器或数据库本身。
答案 3 :(得分:-1)
该错误与MySQLdb完全无关。
您正在使用'+'运算符将字符串与整数合并。您的values
数组包含混合字符串和整数,并且您使用字符串追加运算符添加它们,这不适用于混合str和int(您正在执行类似mystry = 1+','
的操作)。
您的问题的解决方案可以是对数组中的项使用str()。像:
sql2 += str(values[i][j]) + ','