web-dev-qa-db-ja.com

奇妙なSQLAlchemyエラーメッセージ:TypeError: 'dict'オブジェクトはインデックス作成をサポートしていません

SqlAlchemyを使用して、PGデータベースからデータを取得するために、手作りのSQLを使用しています。演算子 '%'のような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は、以前に確立されたデータベースへの接続です。

104

%% in pythonは文字列のフォーマットとして使用されるため、単一の%を使用するため、%として使用するには%を指定する必要があります。その値をこれで置き換えると仮定します。

したがって、クエリで文字列に単一の%を配置する場合は、常に二重%を配置します。

172
Nilesh

SQLAlchemyには、テキストをラップするための text() 関数があり、SQLを正しくエスケープしているように見えます。

つまり.

res = executeSql(sqlalchemy.text(sql))

あなたのために動作し、手動でエスケープする必要がなくなります。

65
user795753

問題は このバグ に関連しているようです。

その場合、回避策としてトリプルエスケープする必要があります。

5
Brian Cain

Sqlalchemy version 1.2 docs で "executeSql"が見つかりませんが、次の行がうまくいきました

engine.execute(sqlalchemy.text(sql_query))

このエラーが表示されたときにもう1つのケースが見つかりました。

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

つまり、パラメーター(%s)クエリでは、クエリパラメータの追加を忘れています。この場合、エラーメッセージは非常に誤解を招くものです。

2
Tupteq

もう1つ注意してください。コメントの_%_文字もエスケープ(または削除)する必要があります。残念ながら、sqlalchemy.text(query_string)はコメント内のパーセント記号をエスケープしません。

1
ClimbsRocks

_%_文字をエスケープしたり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パターンとは異なり、正規表現は、文字列の先頭または末尾に明示的に固定されていない限り、文字列内のどこにでも一致できます。

アンカーの場合、文字列の終わりにアサーション_$_を使用できます(または先頭に_^_)。

0
C8H10N4O2

これは、ケースに起因する可能性もあります-SQLに渡されるパラメーターがDICTギ酸塩で宣言され、LISTまたはTUPPLEの形式でSQLで操作されている場合。