Python MySQLdb:创建表时出现语法错误

时间:2017-09-23 06:17:03

标签: python mysql-python

代码非常简单,我只是直接从控制台运行它,同时, spider.table_name =' crawler'

import MySQLdb
import scrapy

print (spider.table_name)  # >> 'crawler'

db = MySQLdb.connect(........)
db.set_character_set('utf8')
mysql = db.cursor()

sql = "CREATE TABLE %s like r_template;"
mysql.execute(sql, (spider.table_name, ))
db.commit()

但是我得到了语法错误:

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 ''crawler' like r_template' at line 1")

似乎正在执行的实际sql语句是:

CREATE TABLE 'crawler' like r_template

如何单引号''产生的?如何防止它发生?

然后,我尝试了更简单的方法:

mysql.execute(sql, ('crawler', ))
mysql.execute("CREATE TABLE %s like r_template", ('crawler', ))

错误仍然发生。

2 个答案:

答案 0 :(得分:2)

你不小心打开了一扇神秘冒险世界的大门。我的建议是:在看之前不要关上那扇门。

问题是你正试图传递占位符“在左侧”的参数,但你的MySQL界面只适用于“右侧” 。占位符用于,而不是字段名称表格

肤浅的解释

让我从另一个例子开始。

写作是合法的:

where field = %s

如果变量是一个字符串,你的PEP 249兼容接口将正确解释它:把它想象为“在它周围加上引号”(虽然它不是它的作用,否则它将打开SQL注入的大门;但这将说明这一点。

这是在平等的右侧

但如果你写:

where %s = 5

值为'my_field',它不起作用,因为它位于左侧。这不是界面的一部分。

正如你所说,如果你应用相同的逻辑,它会“在它周围加上引号”,所以你会得到:

where 'my_field' = 5

它显然没有意义,因为你得到了你没想到它们的引用(警告:再次,这不是发生了什么,但它说明了这一点)。它不起作用,但是如果你遵循自己的逻辑,那些引用就是你应该得到的。 存在矛盾,所以有些事情显然是错误的。

但是等等!

更深入的解释

重要的是要理解,使用PEP 249接口时,占位符的参数不会转换为字符串,然后放入字符串查询中。它们被翻译成它们的等价物(int等)并在较低级别处理(在解析树或类似结构中,我想)。

已指定机制将参数转换为。它不是为变量标识符而设计的,例如字段表格(这是一种更高级的用例)。

说“标识符是一个变量”是一个非常先进的想法... 我带你进入higher-order programming的精彩世界。

PEP249可以扩展吗?理论上是的,但这不是一个开放和封闭的问题。

解决方案

与此同时,您只剩下一个选项:在>之前插入字符串查询,然后将其提供给SQL引擎。

sql = "CREATE TABLE %s like r_template;" % 'crawler'

我可以想象你身边的人会发出恐怖的颤抖(不要打开那扇门!)。但据我所知,如果你真的希望拥有一个变量表名,那就是你必须要做的。

此时,您可能想问自己为什么要使用变量表名?你是否以其他方式做了一个懒惰的解决方法?在这种情况下,我会回到常规路径并忘记使表或字段变量。

但是,我看到两个用例变量表或字段完全合法:数据库管理构建数据库框架

如果是这种情况,只需谨慎使用字符串插值,以避免无意的SQL注入。你将不得不处理与空白,特殊字符等不同的问题;一个好的做法是“引用”你的字段或表名,例如在标准的MySQL中:

  

`tableaccentuée`

然而,使用ANSI引用:

  

“tableaccentuée”

(如你所见,你 远远没有!)

另外要小心剥掉可能会解散翻译的东西,比如分号。

无论如何,如果你想这样做,你需要远离海岸的视线,直奔日落。你正处于英雄前往左侧之旅的门槛上。您将享受冒险,只要您接受没有救生员来救你。

答案 1 :(得分:0)

使用.format代替%s,这样可以避免查询中的单引号。 例如:

my_sql_query = "CREATE TABLE {}".format(table_name)
mysql.execute(my_sql_query)

这应该有效:)