15

pysqlite を使用して、いくつかのデータで何かを行う手順を作成しています。同じ種類の操作が複数のテーブルと列の同様のフィールドに対して行われるため、次のように sql ステートメントをパラメーター化できると考えました。

def foo():
  column = 'c'
  table = 't'
  row = 1
  # preferred approach, gives syntax error
  c.execute('SELECT ? FROM ? WHERE id=?', (column, table, row))
  # sanity check, works fine
  c.execute('SELECT c FROM t WHERE id=?', (row))
  # workaround, also works, but is this the right way?
  c.execute('SELECT % FROM % WHERE id=?' % (column, table), row))

表示されるエラーはあまり役に立ちませんが ( sqlite3.OperationalError: near "?": syntax error)、要点はわかります。Pysqlite は、このように使用されるプレースホルダーを評価しません。

上記を行う適切な方法とともに、ここで何が起こっているのかを誰かが指摘できますか?

4

2 に答える 2

19

列またはテーブルの名前にプレースホルダーを使用することはできません。私はこれについて正式な引用を持っていません - 私はそれを試して失敗したことからのみこれを「知っています」. ただし、それはある程度理にかなっています。

  • 列とテーブルをパラメータ化できる場合、executeステートメントのすべての部分を置き換えることができるため、フェッチする前に SQL ステートメントを準備 ( -ing) する目的はほとんどありません。
  • pysqlite 1についてはよくわかりませんが、MySQLdb はすべての文字列パラメータを自動的に引用します。列名とテーブル名は引用符で囲まないでください。そのため、プレースホルダーが列またはテーブル名を表しているのか、引用符が必要な値を表しているのかをドライバーが判断しなければならない場合、ドライバーが必要とする解析が複雑になります。

要するに、文字列の書式設定を使用する正しい方法を見つけました。

c.execute('SELECT {} FROM {} WHERE id=?'.format(column, table), row))

1すべてのドライバーがパラメーターを引用するoursqlわけではありません -- SQL と引数をサーバーに別々に送信するため、そうではありません。

于 2012-01-12T20:25:04.913 に答える