【问题标题】:Is it possible to use psycopg2 for prepared statements?是否可以将 psycopg2 用于准备好的语句?
【发布时间】:2021-04-30 17:14:33
【问题描述】:

我正在比较 Postgres 客户端的一些功能的兼容性,我很难让准备好的语句在 Psychopg2 中工作。 Node.js pg 包允许我执行以下操作,其中提供名称 (insert-values) 准备查询服务器端:

    for (let rows = 0; rows < 10; rows++) {
      // Providing a 'name' field allows for prepared statements / bind variables
      const query = {
        name: "insert-values",
        text: "INSERT INTO my_table VALUES($1, $2, $3, $4);",
        values: [Date.now() * 1000, Date.now(), "node pg prep statement", rows],
      }
      const preparedStatement = await client.query(query)
    }

在 Python 中,我正在使用 psycopg2 做这样的事情:

    # insert 10 records
    for x in range(10):
      now = dt.datetime.utcnow()
      date = dt.datetime.now().date()
      cursor.execute("""
        INSERT INTO trades
        VALUES (%s, %s, %s, %s);
        """, (now, date, "python example", x))
    # commit records
    connection.commit()

有没有办法在 Python 中创建准备好的语句?

编辑我正在使用来自QuestDB documentation的样本

【问题讨论】:

    标签: python postgresql questdb


    【解决方案1】:

    即使在 2021 年,Psycopg2 中也不支持预准备语句。是的,您可以执行 PREPARE 并使用带参数的命名查询,但 Psycopg2 不支持与使用 Java JDBC 或 Rust Postgres 驱动程序相同的方式。

    如果您开始使用 INSERT 语句编写循环,则每次迭代都会发送完整的语句文本,并且必须由数据库解析,因此大循环的 IO/CPU 开销将是可衡量的。

    【讨论】:

      【解决方案2】:

      据我所知,不支持“神奇地”准备语句。但是,您可以使用 execute() 执行 SQL PREPAREEXECUTE 语句。

      您可能想阅读手册中关于fast execution helpers 的部分。

      【讨论】:

      • 谢谢提示,我试试cursor.execute_values()
      【解决方案3】:

      为什么不呢?:

      
      date = dt.datetime.now().date()
      insert_sql = """INSERT INTO trades
              VALUES (%s, %s, %s, %s)"""
      # insert 10 records
      for x in range(10):
          now = dt.datetime.utcnow()
          cursor.execute(insert_sql, (now, date, "python example", x))
      # commit records
      connection.commit()
      
      

      结果是一样的。查询构建一次,然后使用 x 的不同参数多次运行。正如@Ture Pålsson 指出的那样,您可以使用此处的助手Fast Execution 来组合INSERTs

      【讨论】:

      • 是的,这是个好主意,但时间戳不会在 for 循环中更新。看起来我仍然缺少要在服务器端编译的语句,这可以在节点的 pg 库中使用“名称”属性。
      • 将时间戳移到循环中。正如@TurePålsson 建议的那样,您可以将PREPARE/EXECUTE 直接与cur.execute() 一起使用。
      猜你喜欢
      • 2010-12-30
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-12-16
      • 1970-01-01
      相关资源
      最近更新 更多