动态表mysqldb python string / int issue

时间:2015-05-13 15:41:33

标签: python mysql-python

在使用静态名称时未获得的表名变量时,尝试将数据写入数据库表时收到错误。由于某些原因我插入的行,如果我插入一个整数作为列值代码运行和表填充,但是,如果我尝试使用字符串我得到SQL语法错误

cursor = db.cursor()
cursor.execute('DROP TABLE IF EXISTS %s' %data[1])

sql ="""CREATE TABLE %s  (IP TEXT, AVAILIBILITY INT)""" %data[1]
cursor.execute(sql)

for key in data[0]:
    cur_ip = key.split(".")[3]
    cursor.execute("""INSERT INTO %s VALUES (%s,%s)""" %(data[1],key,data[0][key]))  
    db.commit()

问题在于我有%(data[1], key, data[0][key])任何想法吗?

1 个答案:

答案 0 :(得分:2)

当您发布实际错误时,分析您的问题有点困难,因为我们必须猜测您的数据实际是什么。但一些一般性观点建议:

使用动态表名通常不是DB系统想要使用的方式。尝试通过使用静态表名称并向表中添加其他键列来考虑是否可以使用该问题。在该字段中,您可以将您现在所做的内容作为动态表名称。通过这种方式,数据库可以更好地优化您的查询,并且您的查询不太可能出错(无需动态创建额外的表一次,这不是一件便宜的事情。此外,您不会有需要动态DROP TABLE查询,这可能会带来安全风险。

所以我解决你的问题的建议是通过试图完全摆脱动态表名来实际解决它。

您遇到的另一个问题是您使用的是python字符串格式,而不是查询本身的参数。这本身就是一个安全问题(SQL-Injections),但也是你的语法错误问题。使用数字时,表达式的计算结果为

INSERT INTO table_name VALUES (100, 200)

哪个是有效的SQL。但是你会得到字符串

INSERT INTO table_name VALUES (Some Text, some more text)

无效(因为字符串周围没有引号'

要解决语法问题和sql-injection-problem问题,请不要将值添加到字符串中,将它们作为列表传递给execute()

cursor.execute("INSERT INTO table_name VALUES (%s,%s)", (key, data[0][key]))

如果您必须拥有动态表名,请先将其放入查询字符串中(例如,使用%格式化),并将查询的实际值作为上述参数给出(因为我无法想象执行会接受表名作为参数)。

将它放在一些简单的示例代码中。现在你正试图这样做:

# don't do this, this won't even work!
table_name = 'some_table'
user_name = 'Peter Smith'
user_age = 47
query = "INSERT INTO %s VALUES (%s, %s)" % (table_name, user_name, user_age)
cursor.execute(query)

创建查询

INSERT INTO some_table VALUES (Peter Smith, 100)

由于不带引号的字符串,这不起作用。所以你需要这样做:

# DON'T DO THIS, it's bad!
query = "INSERT INTO %s VALUES ('%s', %s)" % (table_name, user_name, user_age)

这不是一个好主意,因为你需要知道在哪里放置引号而哪些不是(在某些时候你会搞砸)。更糟糕的是,想象一个名为Connor O'Neal的用户。您会收到语法错误:

INSERT INTO some_table VALUES ('Connor O'Neal', 100)

(这也是sql-injections用于粉碎系统/窃取数据的方式)。所以你还需要注意转义字符串的值。变得更复杂。

将这些问题留给python和mysql,将日期(不是表名)作为参数传递给执行!

table_name = 'some_table'
user_name = 'Peter Smith'
user_age = 47
query = "INSERT INTO " + table_name + " VALUES (%s, %s)"
cursor.execute(query, (user_name, user_age))

这样您甚至可以直接传递datetime个对象。除了使用%s之外,还有其他方式来放置数据,看一下这个例子http://dev.mysql.com/doc/connector-python/en/connector-python-api-mysqlcursor-execute.html(那里使用的是python3,我不知道你使用哪个 - 但除了{ {1}}语句也应该与python2一起使用,我认为。)