Подтвердить что ты не робот

Сообщение об ошибке Strange SQLAlchemy: TypeError: объект 'dict' не поддерживает индексирование

Я использую ручной 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()

Кто-нибудь знает, что вызывает это вводящее в заблуждение сообщение об ошибке, и как я могу его исправить?

[[Edit]]

Прежде чем кто-либо спросит, нет ничего особенного или не интересует функции, включенные выше. Например, функция executeSql() просто вызывает conn.execute(sql) и возвращает результаты. Переменная conn - это просто ранее установленное соединение с базой данных.

4b9b3361

Ответ 1

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

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

Ответ 2

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

Т.е.

res = executeSql(sqlalchemy.text(sql))

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

Ответ 3

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

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

Ответ 4

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

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

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

Ответ 5

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

engine.execute(sqlalchemy.text(sql_query))

Ответ 6

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

Ответ 7

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

Ответ 8

Другой способ решить вашу проблему, если вы не хотите экранировать символы % или использовать 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 и regex описаны в документации по сопоставлению с образцом.

Обратите внимание, что:

В отличие от шаблонов LIKE, регулярному выражению разрешено совпадать в любом месте строки, если только регулярное выражение явно не привязано к началу или концу строки.

Для привязки вы можете использовать утверждение $ для конца строки (или ^ для начала).