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は、以前に確立されたデータベースへの接続です。
%%
in pythonは文字列のフォーマットとして使用されるため、単一の%
を使用するため、%
として使用するには%
を指定する必要があります。その値をこれで置き換えると仮定します。
したがって、クエリで文字列に単一の%
を配置する場合は、常に二重%
を配置します。
SQLAlchemyには、テキストをラップするための text()
関数があり、SQLを正しくエスケープしているように見えます。
つまり.
res = executeSql(sqlalchemy.text(sql))
あなたのために動作し、手動でエスケープする必要がなくなります。
問題は このバグ に関連しているようです。
その場合、回避策としてトリプルエスケープする必要があります。
Sqlalchemy version 1.2 docs で "executeSql"が見つかりませんが、次の行がうまくいきました
engine.execute(sqlalchemy.text(sql_query))
このエラーが表示されたときにもう1つのケースが見つかりました。
c.execute("SELECT * FROM t WHERE a = %s")
つまり、パラメーター(%s
)クエリでは、クエリパラメータの追加を忘れています。この場合、エラーメッセージは非常に誤解を招くものです。
もう1つ注意してください。コメントの_%
_文字もエスケープ(または削除)する必要があります。残念ながら、sqlalchemy.text(query_string)
はコメント内のパーセント記号をエスケープしません。
_%
_文字をエスケープしたり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パターンとは異なり、正規表現は、文字列の先頭または末尾に明示的に固定されていない限り、文字列内のどこにでも一致できます。
アンカーの場合、文字列の終わりにアサーション_$
_を使用できます(または先頭に_^
_)。
これは、ケースに起因する可能性もあります-SQLに渡されるパラメーターがDICTギ酸塩で宣言され、LISTまたはTUPPLEの形式でSQLで操作されている場合。