使用MySQLdb向MySql服务器添加整数和字符串

时间:2011-07-28 21:05:46

标签: python mysql sql database string-formatting

我正在使用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。

4 个答案:

答案 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.joinstr.format

实际上,您应该使用参数化查询,该查询将值放入字符串中,以推送到数据库连接器或数据库本身。

答案 3 :(得分:-1)

该错误与MySQLdb完全无关。

您正在使用'+'运算符将字符串与整数合并。您的values数组包含混合字符串和整数,并且您使用字符串追加运算符添加它们,这不适用于混合str和int(您正在执行类似mystry = 1+','的操作)。

您的问题的解决方案可以是对数组中的项使用str()。像:

sql2 += str(values[i][j]) + ','