Psycopg2插入带占位符的表中

Tim*_*ton 17 python postgresql postgis psycopg2 psycopg

这可能是一个相当愚蠢的问题,但我在这里做错了什么?它创建表但INSERT INTO不起作用,我想我的占位符有问题吗?

conn = psycopg2.connect("dbname=postgres user=postgres")
cur = conn.cursor()
escaped_name = "TOUR_2"
cur.execute('CREATE TABLE %s(id serial PRIMARY KEY, day date, elapsed_time varchar,    net_time varchar, length float, average_speed float, geometry GEOMETRY);' % escaped_name)

cur.execute('INSERT INTO %s (day,elapsed_time, net_time, length, average_speed, geometry) VALUES (%s, %s, %s, %s, %s, %s)', (escaped_name, day ,time_length,  time_length_net, length_km, avg_speed,  myLine_ppy))

conn.commit()
cur.close()
conn.close()
Run Code Online (Sandbox Code Playgroud)

INSERT INTO调用不起作用,它给了我

cur.execute('INSERT INTO %s (day,elapsed_time, net_time, length, average_speed,  
geometry) VALUES (%s, %s, %s, %s, %s, %s)'% (escaped_name, day ,time_length,  
time_length_net, length_km, avg_speed,  myLine_ppy))
psycopg2.ProgrammingError: syntax error at or near ":"
LINE 1: ...h, average_speed, geometry) VALUES (2013/09/01 , 2:56:59, 02...
Run Code Online (Sandbox Code Playgroud)

有人可以帮我这个吗?谢谢你!

fog*_*fog 29

您正在使用Python字符串格式,这是一个非常糟糕的想法(TM).想想SQL注入.正确的方法是使用绑定变量:

cur.execute('INSERT INTO %s (day, elapsed_time, net_time, length, average_speed, geometry) VALUES (%s, %s, %s, %s, %s, %s)', (escaped_name, day, time_length, time_length_net, length_km, avg_speed, myLine_ppy))
Run Code Online (Sandbox Code Playgroud)

其中参数元组作为第二个参数给出execute().此外,您不需要转义任何值,psycopg2将为您进行转义.在这种特殊情况下,还建议不要在变量(escaped_name)中传递表名,而是将其嵌入查询字符串中:psycopg2不知道如何引用表和列名,只引用值.

请参阅psycopg2文档:

http://www.psycopg.org/psycopg/docs/usage.html#passing-parameters-to-sql-queries

如果要以编程方式生成SQL语句,通常的方法是使用Python格式化语句和参数的变量绑定.例如,如果你有表名,escaped_name你可以这样做:

query = "INSERT INTO %s (col1, ...) VALUES (%%s, ...)" % escaped_name
curs.execute(query, args_tuple)
Run Code Online (Sandbox Code Playgroud)

显然,要在查询中使用占位符,您需要引用任何%以第一种格式引入绑定参数的引用.

请注意,这是安全的,当且仅当 escaped_name您的代码生成时忽略任何外部输入(例如表基名和计数器),但如果您使用用户提供的数据,则存在SQL注入的风险.

  • +1引用文档:"*警告永远不要,永远不要使用Python字符串连接(+)或字符串参数插值(%)将变量传递给SQL查询字符串.甚至不用枪口.*" (5认同)
  • @TimothyDalton隐藏在[docs](http://initd.org/psycopg/docs/usage.html)中:`当使用参数时,为了在查询中包含文字%,你可以使用%% string` (3认同)
  • @TimothyDalton“自动”生成 SQL 语句的惯用方法是使用 Python 格式来构建语句和变量绑定来传递参数。请参阅我更新的答案。 (2认同)
  • 再次感谢雾,它现在可以使用“%%”作为我的值,而不仅仅是“%”。我在网上找不到任何与此相关的信息。第二个“%”指示语句从第二个参数中获取值,在本例中是“args_tuple”,对吧? (2认同)

Eri*_*ith 11

为了扩展@Matt的答案,占位符不适用于表名之类的标识符,因为该名称将被引用为字符串值并导致无效语法。

如果你想动态生成这样的查询,你可以使用引用的pyscopg2.sql模块

from psycopg2.sql import Identifier, SQL

cur.execute(SQL("INSERT INTO {} VALUES (%s)").format(Identifier('my_table')), (10,))
Run Code Online (Sandbox Code Playgroud)