Python MySQLdb:create tab时语法错误

2024-05-04 05:13:28 发布

您现在位置:Python中文网/ 问答频道 /正文

代码非常简单,我只是直接从控制台运行,同时,spider.table_名称='爬虫'

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()

但我发现语法错误:

^{pr2}$

看起来实际执行的sql语句是:

CREATE TABLE 'crawler' like r_template

单引号“”是如何生成的?如何防止它发生?

然后,我试着用更简单的方法:

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

错误仍然发生。


Tags: nameimportexecutedbsqlcreatemysqltable
2条回答

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

问题是,您试图在左侧传递占位符“”,但您与MySQL的接口只在“右侧”上工作。占位符用于,而不是用于字段名。在

肤浅的解释

让我从另一个例子开始。在

合法的做法是:

where field = %s

如果变量是一个字符串,那么与pep249兼容的接口将正确地解释它:将其视为“在它周围加引号”(尽管它不是这样做的,否则它将为SQL注入打开大门;但这将说明这一点)。在

在等式的右边。在

但如果你写:

^{pr2}$

如果值为“my_field”,则它将不起作用,因为它位于左侧。这不是接口的一部分。在

正如您所说,如果您应用相同的逻辑,它将“加引号”,因此您将得到:

where 'my_field' = 5

这显然是没有道理的,因为你得到了你意想不到的报价(注意:再次说明,这不是发生的事情,但它说明了问题所在)。如果你还不明白你的逻辑。这是一个矛盾,显然出了问题。

但是等等!在

更深入的解释

理解pep249接口时,占位符的参数不会转换为字符串,然后放入字符串查询中,这一点很重要。它们被转换成它们的等价物(int等),并在较低的层次上进行处理(我想是在解析树或类似的结构中)。在

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

说“标识符是一个变量”是一个非常先进的想法…我让您进入higher-order programming的奇妙世界。在

PEP249是否可以扩展到这一点?理论上是的,但这不是一个开放式的问题。在

解决方案

同时,您只剩下一个选项:在将字符串查询交给SQL引擎之前对其进行插值。在

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

我可以想象你周围的人恐惧的颤抖(别打开那扇门!)。但据我所知,如果你真的想要一个变量表名,那就是你必须要做的。在

这时,您可能想问自己为什么要使用变量表名?你这么做是为了别的事而懒散地解决问题吗?在这种情况下,我会回到惯常做法而忘记使表或字段变为变量。在

对于两个数据库的情况,请参见使用数据库的情况。在

如果是这样,只需小心使用字符串插值,以避免意外的SQL注入。您必须处理空白、特殊字符等不同的问题;一个好的做法是“引用”字段或表名,例如在标准MySQL中:

`table accentuée`

鉴于ANSI引用:

"table accentuée"

(如你所见,你并不遥远!)在

还要注意去掉可能会使解释器脱落的东西,比如分号。在

不管怎样,如果你想这样做,你需要在看不到海岸的地方,直接朝着日落的方向航行。你在吗h英雄向左侧的旅程。只要你接受没有救生员来救你,你就会享受这次冒险。在

使用.format而不是%s这将允许您在查询中避免使用单引号。 例如:

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

这应该行得通:)

相关问题 更多 >