Странное сообщение об ошибке SQLAlchemy: TypeError: объект dict не поддерживает индексирование - PullRequest
101 голосов
/ 28 декабря 2011

Я использую созданный вручную SQL для извлечения данных из базы данных PG, используя SqlAlchemy. Я пытаюсь запрос, который содержит 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 - это просто ранее установленное соединение с базой данных.

Ответы [ 8 ]

165 голосов
/ 29 декабря 2011

Вы должны указать %%, чтобы использовать его как %, потому что % в python используется как форматирование строки, поэтому, когда вы пишете одиночный %, предполагается, что вы собираетесь заменить какое-то значение этим.

Поэтому, если вы хотите поместить один % в строку с запросом, всегда ставьте double %.

61 голосов
/ 20 февраля 2013

SQLAlchemy имеет функцию text() для переноса текста, который, по-видимому, корректно экранирует SQL для вас.

Т.е.

res = executeSql(sqlalchemy.text(sql))

должно работать на вас и избавить вас от необходимости вручную убегать.

5 голосов
/ 28 декабря 2011

Похоже, что ваша проблема может быть связана с этой ошибкой .

В этом случае вы должны использовать тройной выход как обходной путь.

2 голосов
/ 14 марта 2018

Я не могу найти "executeSql" в sqlalchemy версия 1.2, документы , но приведенная ниже строка работает для меня

engine.execute(sqlalchemy.text(sql_query))
2 голосов
/ 04 апреля 2016

Я обнаружил еще один случай, когда появляется эта ошибка:

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

Другими словами, если вы предоставляете параметр (%s) в запросе, но забыли добавить параметры запроса.В этом случае сообщение об ошибке вводит в заблуждение.

1 голос
/ 30 сентября 2017

Еще одно примечание - вы должны экранировать (или удалить) % символов в комментариях.К сожалению, sqlalchemy.text(query_string) не избегает знаков процента в комментариях.

0 голосов
/ 08 июля 2019

Другой способ решения вашей проблемы, если вы не хотите экранировать % символов или использовать 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 голосов
/ 11 мая 2015

Это также может быть следствием случая - в случае, если параметры, передаваемые в SQL, объявлены в формате DICT и обрабатываются в SQL в форме LIST или TUPPLE.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...