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-ing)SQL 语句就没有什么意义了,因为语句的所有部分都可以替换。
  • 我不确定 pysqlite 1,但 MySQLdb 会自动引用所有字符串参数。不应引用列名和表名。因此,如果驱动程序必须决定占位符是代表列名或表名还是需要引用的值,它将使驱动程序所需的解析变得复杂。

简而言之,您找到了正确的方法——使用字符串格式化。

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

1并非所有驱动程序都引用参数——oursql没有,因为它分别向服务器发送 SQL 和参数。

于 2012-01-12T20:25:04.913 回答
2

正如@unutbu 回答的那样,没有办法为表/列名使用占位符。我的建议是做你现在正在做的事情,但也要引用表名以保护自己免受可能有奇怪名称的表或列的影响。

SQL 标准对反引号(`)的使用有何规定?已经在一定程度上解释了这一点,尽管该答案有意见,但我想说,在你的情况下,引用是个好主意。

于 2012-05-23T09:40:30.473 回答