Psycopg2 使用占位符插入表格

Posted

技术标签:

【中文标题】Psycopg2 使用占位符插入表格【英文标题】:Psycopg2 Insert Into Table with Placeholders 【发布时间】:2013-10-14 16:00:06 【问题描述】:

这可能是一个相当愚蠢的问题,但我在这里做错了什么?它创建了表格,但 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()

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...

有人可以帮我解决这个问题吗?非常感谢!

【问题讨论】:

【参考方案1】:

您正在使用 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))

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

参见 psycopg2 文档:

https://www.psycopg.org/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)

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

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

【讨论】:

+1 引用文档:“警告永远不要,永远不要,永远不要使用 Python 字符串连接 (+) 或字符串参数插值 (%) 将变量传递给 SQL 查询字符串。甚至没有在枪口下。" 谢谢雾,我现在明白了。我一直在寻找解决方案,因为我想自动化创建具有连续数字的表的过程,即。 e. TOUR+'i' 其中 'i' 是一个数字,并不总是写一个新的 SQL 语句。你知道怎么做吗? @TimothyDalton “自动”生成 SQL 语句的惯用方法是使用 Python 格式来构建语句和变量绑定以传递参数。请参阅我的更新答案。 再次感谢雾,它现在可以使用%% 作为我的值,而不仅仅是%。我在网上找不到任何关于此的内容。第二个% 指示语句从我的第二个参数中获取值,在本例中是args_tuple,对吧? @TimothyDalton 隐藏在docs:When parameters are used, in order to include a literal % in the query you can use the %% string【参考方案2】:

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

如果要动态生成这样的查询,可以使用referred to pyscopg2.sql module:

from psycopg2.sql import Identifier, SQL

cur.execute(SQL("INSERT INTO  VALUES (%s)").format(Identifier('my_table')), (10,))

【讨论】:

【参考方案3】:

psycopg2 v2.7 开始,有一种支持的方式来执行此操作:see the psycopg2.sql docs。

【讨论】:

这里有个更具体的例子就好了。

以上是关于Psycopg2 使用占位符插入表格的主要内容,如果未能解决你的问题,请参考以下文章

使用空占位符将图像插入幻灯片(PowerPoint)

当我以 pdf 形式将值插入占位符时,如何为 iText 设置编码?

Wordpress 中的占位符图标联系表格 7

使用 jQuery-UI Sortable 控制占位符高度

如何在 UITextView 中插入占位符? [复制]

HTML 表格占位符错误