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


145

私はSqlAlchemyを使用して、手作りのSQLを使用して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私はそれを逃した。問題の原因となっているSQLには「RETURNING *」はありません。質問を訂正します。
ホムンクルスレティキュリ2011

1
この回答は役に立ちましたか[ stackoverflow.com/questions/3944276/…役に立ちましたか?
バン

2
@バン:ありがとう!はい、そうです。「%」の代わりに「\ %%」を使用する必要がありました。ステートメントは正しく実行されるようになりました。
ホムンクルスレティキュリ

3
すごい。完全を期すために役立った短い回答を投稿してください(受け入れてください)。
van

回答:


227

Pythonでは文字列のフォーマット%%として使用される%ため%、それを使用することを許可する%必要があります。そのため、singleを記述する場合、値をこれで置き換えると想定します。

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


27
彼らがそのエラーメッセージを更新してくれるといいのですが、メッセージが表示されるたびに、このページに
アクセスして

86

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

すなわち

res = executeSql(sqlalchemy.text(sql))

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


13
これが選択された答えです。私の場合、問題は解決しました。
Gani Simsek 2017

1
これはコメントをエスケープしませんが、それ以外の場合は素晴らしい解決策です。
ClimbsRocks 2017

それは私にとってはうまく
いき



2

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

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

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


1

もう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

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

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.