字符串插值导致MySQL数据库错误
我在使用mysqlDB的时候遇到了一个让我很困惑的问题。
我的问题主要集中在下面这些执行语句中的表名上。
这个是可以正常工作的:
c.execute(u'''insert into AIN0 (Date_Info, Raw_Data, Calculation_Formula, Calculated_Data) values (%s, %s, %s, %s)''',
(str(date), int(raw), int(formula), 0.1))
而这两个则不行:
c.execute(u'''insert into %s (Date_Info, Raw_Data, Calculation_Formula, Calculated_Data) values (%s, %s, %s, %s)''',
(str("AIN0"), str(date), int(raw), int(formula), 0.1))
c.execute(u'''insert into 'AIN0' (Date_Info, Raw_Data, Calculation_Formula, Calculated_Data) values (%s, %s, %s, %s)''',
(str(date), int(raw), int(formula), 0.1))
问题是,这两个不工作的语句都给出了同样的错误信息:
ProgrammingError: (1064, "你的SQL语法有错误;请检查与你的MySQL服务器版本相对应的手册,看看在 ''AIN0' (Date_Info, Raw_Data, Calculation_Formula, Calculated_Data) values ('2011' 的第1行附近应该使用什么正确的语法")
注意,在错误信息中,AIN0是被单引号包围的,即使在我使用字符串插值操作符插入它的情况下也是如此。为了确认这一点,我故意在可以正常工作的情况下制造了一个语法错误,以便看看MySQL是怎么处理的。
ProgrammingError: (1064, "你的SQL语法有错误;请检查与你的MySQL服务器版本相对应的手册,看看在')) AIN0 (Date_Info, Raw_Data, Calculation_Formula, Calculated_Data) values ('201' 的第1行附近应该使用什么正确的语法")
果然,在MySQL正常工作的那个例子中,AIN0并没有被单引号包围,这让我相信这就是导致错误的原因。
为什么在我使用字符串插值时,单引号会被插入到我的字符串周围?我该如何让它们不再出现?
1 个回答
如果你说的“字符串插值”是指像Python中的字符串格式化,那你用的其实不是这个。cursor.execute()
是用来插入SQL参数的,它有自己的一套规则。之所以会混淆,是因为一些数据库接口(包括mysqlDB)使用%s
作为占位符,而其他数据库接口可能使用?
。
当你使用参数化的SQL时,占位符只能出现在SQL中可以放表达式的地方。表名就不是一个表达式。当你的参数是字符串时,它会被单引号包裹,这样在生成的SQL中看起来就像是一个SQL字符串字面量。这就涉及到单引号的加倍,比如在Python中表示的字符串字面量"O'Brien"
在SQL中会变成'O''Brien'
。
所以,你无法阻止它在周围加上单引号。你需要做两个步骤:(1)构建一个SQL字符串,在你想要的位置插入AIN0
,使用Python的字符串格式化;(2)在你的cursor.execute()
中使用这个SQL字符串。