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

我正在使用手工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只是先前建立的与数据库的连接。

I am using hand crafted SQL to fetch data from a PG database, using SqlAlchemy. I am trying a query which contains the SQL like operator ‘%’ and that seems to throw SqlAlcjhemy through a loop:

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

Any one knows what is causing this misleading error message and how I may fix it?

[[Edit]]

Before any one asks, there is nothing special or fancy about the functions included above. For example the function executeSql() simply invokes conn.execute(sql) and returns the results. The variable conn is simply the previously established connection to the database.


回答 0

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

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

You have to give %% to use it as % because % in python is use as string formatting so when you write single % its assume that you are going to replace some value with this.

So when you want to place single % in string with query allways place double %.


回答 1

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

res = executeSql(sqlalchemy.text(sql))

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

SQLAlchemy has a text() function for wrapping text which appears to correctly escape the SQL for you.

I.e.

res = executeSql(sqlalchemy.text(sql))

should work for you and save you from having to do the manual escaping.


回答 2

我在sqlalchemy 1.2版文档中找不到“ executeSql” ,但以下代码对我有用

engine.execute(sqlalchemy.text(sql_query))

I cannot find the “executeSql” in sqlalchemy version 1.2 docs , but the below line worked for me

engine.execute(sqlalchemy.text(sql_query))

回答 3

看来您的问题可能与此bug有关

在这种情况下,您应该使用三倍转义来解决。

It seems like your problem may be related to this bug.

In which case, you should triple-escape as a workaround.


回答 4

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

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

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

I found one more case when this error shows up:

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

In other words, if you provide parameter (%s) in query, but you forget to add query params. In this case error message is very misleading.


回答 5

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

One more note- you must escape (or delete) % characters in comments as well. Unfortunately, sqlalchemy.text(query_string) does not escape the percent signs in the comments.


回答 6

如果您不想转义%字符或使用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模式不同,除非将正则表达式明确地锚定到字符串的开头或结尾,否则允许在字符串中的任何位置匹配正则表达式。

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

Another way of solving your problem, if you don’t want to escape % characters or use sqlalchemy.text(), is to use a regular expression.

Instead of:

select id from ref_geog where short_name LIKE '%opt'

Try (for case-sensitive match):

select id from ref_geog where short_name ~ 'opt$' 

or (for case-insensitive):

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

Both LIKE and regex are covered in the documentation on pattern matching.

Note that:

Unlike LIKE patterns, a regular expression is allowed to match anywhere within a string, unless the regular expression is explicitly anchored to the beginning or end of the string.

For an anchor, you can use the assertion $ for end of string (or ^ for beginning).


回答 7

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

This could also result from the case – in case parameters to be passed onto the SQL are declared in DICT formate and are being manipulated in the SQL in the form of LIST or TUPPLE.


声明:本站所有文章,如无特殊说明或标注,均为本站原创发布。任何个人或组织,在未征得本站同意时,禁止复制、盗用、采集、发布本站内容到任何网站、书籍等各类媒体平台。如若本站内容侵犯了原著者的合法权益,可联系我们进行处理。