4

フォーマットオプションを使用してpsycopg2を使用してpostgresで作成するために変数タイプ名を渡すと、オブジェクト名の不正な文字列フォーマットでエラーがスローされました。クエリパラメータ内で%sを使用して名前を渡すことは許可されていませんか?

私の問題を解決するために私が書いたコードは以下のとおりです(これを解決するためのより良い方法を探しているだけです)

cursor.execute("CREATE TYPE {0} AS ENUM %s".format(name), (tuple(set([e.upper() for e in elements])),))
4

3 に答える 3

2

実際には、クエリをPython形式にすることは絶対にしないでください。ただし、 psycopg2に任せてください。これを作成する方法は次のとおりです。http://initd.org/psycopg/docs/usage.html#passing-parameters-to-sql-queries ie:

cur.execute("INSERT INTO numbers VALUES (%s)", (42,))

2.7バージョン以降、いくつかの高度なフォーマットの可能性がpsycopg2.sqlモジュールを通じて利用可能になります:http: //initd.org/psycopg/docs/sql.html

于 2017-01-09T15:46:09.797 に答える
1

ご想像のとおり、テーブル名などをクエリパラメータとして渡すことはできません。

それらはプロトコルレベルのバインドパラメータとして送信され、(重要なことに)クエリはプレースホルダーとして有効なSQLとして解析可能である必要があります。これは、SQLレベルを実行してから、PREPAREを分離する場合と同じですEXECUTE。適切な識別子の引用符を使用して、準備する前にSQL文字列にフォーマットする必要があります。

置換する識別子を二重引用符で囲み、渡される文字列内で引用符で囲まれたシーケンスを途中で終了する可能性のある二重引用符に注意してください。これらは2倍にする必要があります。たとえば、テーブル名some"tableには次のものを使用します。

 'SELECT * FROM "{0}"'.format('some""table');

SQLインジェクションは非常に深刻なリスクです。あなたはあなたの引用を正確に正しくしなければなりません。理想的には、PostgreSQLSQL関数に相当するクライアント側を見つけますquote_ident

二重引用符で囲まれた識別子では大文字と小文字が区別されることに注意してください。常に二重引用符で囲まれた識別子を使用して、DBで同じ大文字と小文字を区別して作成してください。引用符で囲まれた識別子と引用符で囲まれていない識別子を混在させないでください。

于 2012-10-08T09:37:21.677 に答える
0

私もこの問題に遭遇し、文字列フォーマットを使用したリモートデータベースへの接続をカバーする短いブログ投稿を書きましたが、この問題と私の解決策は、SQLコマンドに変数を渡す必要があるすべての状況に適用できます。

この問題を回避する方法は次のとおりです。

import psycopg2 as db
import sys

my_host = 'ec2-190-111-829-829.compute-1.amazonaws.com'
my_dbname = 'myDBNameGoesHere'
my_user = 'myUsernameGoesHere'
my_password = 'myPasswordGoesHere'
remote_connection_str = 'host={0} dbname={1} user={2} password={3}'.format(my_host, my_dbname, my_user, my_password)

if __name__ == '__main__':
     try:
          remote_connection = db.connect(remote_connection_str)
          cursor = remote_connection.cursor()
          cursor.execute('SELECT version()')
          version = cursor.fetchone()
          print "\n"
          print "Successful connection to database."
          print "Database information:\n", version
          print "\n"

     except db.DatabaseError, e:
          print 'Error %s' % e
          sys.exit(1)

     finally:
          if remote_connection:
          remote_connection.close()
于 2013-10-07T13:58:21.270 に答える