【问题标题】:psycopg2: formatting data values in execute_valuespsycopg2:在 execute_values 中格式化数据值
【发布时间】:2021-03-03 18:04:08
【问题描述】:

我正在尝试使用psycopg2 中的execute_many 函数将多行插入到我的PostgreSQL 表中。我可以让它处理简单的值,我不能让它处理更复杂的数据。

以下说明了我正在尝试做的事情:

dataset = [[1,'2020-11-01 00:00:00', 1],[2,'localtimestamp', None],[3, '2020-11-01 00:00:00', '(select otherid from myothertable where otherid = 99)']]
queryText = "insert into mytable (id,timestamp,fk_id) values %s"
execute_values(cursor,querytext,dataset,template=None)

如您所见,我正在尝试使用 localtimestamp 函数填充一个字段,并使用嵌入式 select 填充另一个具有 FKed 表中的 ID 的字段。

当在execute_many 函数中创建插入查询时,localtimestamp 和嵌入式选择被包裹在引号中,这很公平,因为它们是字符串。所以我的问题是,有没有办法告诉execute_values 不要将数据值括在引号中?

我可以通过使用 ISO 日期字符串填充 dataset 相对轻松地绕过使用 localtimestamp 的需要,但是让嵌入式查询工作更加复杂。我试图不自己构建查询,只是使用conn.execute(...),原因很明显,这不是一种安全的方法。

任何建议都非常感谢。谢谢

【问题讨论】:

  • 您正试图将值与 SQL 混合,这是一个非常糟糕的主意。您的代码不起作用,因为 psycopg2 可以防止 SQL 注入。
  • 正如@MikeOrganek 所说,这是行不通的,因为execute_values 只期望该值而不是查询。不知道为什么你认为conn.execute() 不安全?
  • 是的,不幸的是,这正是我想要做的。我知道 SQL 注入的可能性并在代码中说明了这一点。不过谢谢你的回复。所以,基本上有很好的理由,psycopg2 不会让我做我想做的事。我会以不同的方式处理这件事。干杯。
  • @AdrianKlaver:如果我不能确保 SQL 是干净的,那么“不安全”就像对 SQL 注入开放一样,我希望我可以回复 psycopg2 来帮助我解决这个问题。但看起来我将不得不构建我的 onw SQL 并使用conn.execute()(无论如何我都是先这样做的,我只是认为有一个更优雅的解决方案)
  • execute() 将接受parameters。还有sql 模块可以帮助安全地构建动态查询。如果您是构建查询的人,那么我认为没有问题。

标签: python sql database postgresql psycopg2


【解决方案1】:

您可以使用AsIs,以防止您的子查询被引用:

dataset = [[1,'2020-11-01 00:00:00', 1],[2,'2020-11-01 00:00:00', None],[3, '2020-11-01 00:00:00', "(select id from __users where lastname = 'Reinisch')"]]

for i, data in enumerate(dataset):
    if isinstance(data[2], str):
        data[2] = AsIs(data[2])
    # same here for the functions

queryText = "insert into mytable (id,ts,fk_id) values %s"
execute_values(cursor,queryText,dataset,template=None)

cursor.execute('select * from mytable')
pprint.pprint(cursor.fetchall())

输出:

[(1, datetime.datetime(2020, 11, 1, 0, 0), 1),
 (2, datetime.datetime(2020, 11, 1, 0, 0), None),
 (3, datetime.datetime(2020, 11, 1, 0, 0), 366211)]

注意

我没有检查 postgres 函数,但应该可以像 SELECT localtimestamp() 一样工作,但如上所述它不是保存!

【讨论】:

  • 由于 Daniele Varrazzo(piro) 在此 SO answer 中提到的原因,我会小心这一点
猜你喜欢
  • 1970-01-01
  • 2021-06-05
  • 2019-02-19
  • 1970-01-01
  • 2021-09-28
  • 1970-01-01
  • 1970-01-01
  • 2013-06-11
  • 2017-05-19
相关资源
最近更新 更多