2

Python で cx_Oracle を使用していますが、次の簡単な例のように、変数をテーブル名として使用できません。

query = "select * from some.:usertable.userinfo"

bindvars = {'usertable':usertable}

cursor.execute(query, bindvars)

正しい構文は何ですか? …などを使用すると、変数の置換は正常に機能WHEREしますが、テーブル名では機能しません。どうにかして ":usertable" を分けないといけないのかな…</p>

4

3 に答える 3

3

データベース アダプターは、「値」以外 (引用符が必要なもの) のパラメーターの使用をほとんどサポートしていません。文字列の書式設定を使用するか (危険です。SQL インジェクションのリスクがあります)、Python コードを使用して有効な SQL を生成できる SQLAlchemy のようなライブラリを使用します。

値が適切であると確信している場合usertable(たとえば、既存のテーブル名のリストと照らし合わせてチェックした場合)、次のように動作します。

query = 'select * from some.{usertable}.userinfo'.format(usertable=usertable)
于 2012-10-29T15:54:49.237 に答える
2

Oracle ではオブジェクト名をバインドできず、リテラルのみをバインドできます。dbms_assertただし、動的オブジェクト名を使用する際に SQL インジェクションを防ぐために、Oracle には組み込みのパッケージがあります。あなたのケースで最も便利な関数はおそらくsql_object_nameで、これは次のとおりです。

「... 入力パラメータ文字列が既存の SQL オブジェクトの修飾された SQL 識別子であることを確認します。」

たとえば、cx_Oracle で次のことを行うことができます。

object_name = cursor.callfunc('sys.dbms_assert.sql_object_name'
                             , cx_Oracle.string, ['usertable'])

名前が無効な場合は ORA-44002 が発生します。これは cx_Oracleで取得できます。または、Martijn が提案したようにすべてが問題ない場合は続行します。

SQL インジェクションを防ぐための Oracle のガイドを読むことをお勧めします。

于 2012-10-29T18:11:46.063 に答える