奇怪的SQLAlchemy错误消息:TypeError:'dict'对象不支持索引


145

我正在使用手工SQL,使用SqlAlchemy从PG数据库中获取数据。我正在尝试一个查询,其中包含类似运算符'%'的SQL,并且该查询似乎通过循环抛出SqlAlcjhemy:

sql = """
       SELECT DISTINCT u.name from user u
        INNER JOIN city c ON u.city_id = c.id
        WHERE c.designation=upper('fantasy') 
        AND c.id IN (select id from ref_geog where short_name LIKE '%opt')
      """

# The last line in the above statement throws the error mentioned in the title. 
# However if the last line is change to:
# AND c.id IN (select id from ref_geog where short_name = 'helloopt')
# the script runs correctly.
#
# I also tried double escaping the '%' i.e. using '%%' instead - that generated the same error as previously.

connectDb()
res = executeSql(sql)
print res
closeDbConnection()

谁知道是什么原因导致了这种误导性错误消息,以及我该如何解决?

[[编辑]]

在任何人问之前,上面所包含的功能没有什么特别或特别的地方。例如,函数executeSql()仅调用conn.execute(sql)并返回结果。变量conn只是先前建立的与数据库的连接。


您可以发布的代码executeSql(...)吗?而且,您确实RETURNING *SELECT声明中有吗?
van

@van我错过了那个。SQL中没有导致问题的“ RETURNING *”。我会纠正这个问题。
Homunculus Reticulli 2011年

1
这个答案[ stackoverflow.com/questions/3944276 / ...有用吗?
van

2
@van:谢谢!是的,它确实。我必须使用“ \ %%”而不是“%”。现在,该语句已正确执行。
Homunculus Reticulli 2011年

3
大。请发表简短的答案(并接受它),以确保完整性。
van

Answers:


227

您必须%%使用它,%因为%在python中它被用作字符串格式,因此当您编写单个时,%它会假定您将用此值替换某些值。

因此,当您要%在查询中始终将string放置为all时,请放置double %


27
我希望他们会更新该错误消息,每次我得到它时,我都会落在此页面上并回答
oshi2016年

86

SQLAlchemy具有text()包装文本的功能,该文本似乎可以为您正确地转义SQL。

res = executeSql(sqlalchemy.text(sql))

应该可以为您工作,并使您不必进行手动转义。


13
这应该是选定的答案。它解决了我的问题。
加尼·辛塞克

1
请注意,这不会转义注释,但否则将是一个绝妙的解决方案。
ClimbsRocks

这对我有用,并且比用双%更改所有查询更容易实现
Philippe Oger



2

当出现此错误时,我发现了另一种情况:

c.execute("SELECT * FROM t WHERE a = %s")

换句话说,如果您%s在查询中提供参数(),但您忘记添加查询参数。在这种情况下,错误消息非常容易引起误解。


1

还有一个注意事项-您还必须转义(或删除)%注释中的字符。不幸的是,sqlalchemy.text(query_string)不能逃脱评论中的百分号。


1

如果您不想转义%字符或使用sqlalchemy.text(),则解决问题的另一种方法是使用正则表达式。

代替:

select id from ref_geog where short_name LIKE '%opt'

尝试(区分大小写的匹配):

select id from ref_geog where short_name ~ 'opt$' 

或(不区分大小写):

select id from ref_geog where short_name ~* 'opt$'

两个LIKE和正则表达式被覆盖中模式匹配的文档

注意:

与LIKE模式不同,除非将正则表达式明确地锚定到字符串的开头或结尾,否则允许在字符串中的任何位置匹配正则表达式。

对于锚,可以将断言$用于字符串的结尾(或^开头)。


0

这也可能是由于这种情况-如果要在DICT formate中声明要传递到SQL的参数,并在SQL中以LIST或TUPPLE的形式对其进行操作。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.