【问题标题】:SQL INSERT with multiple rows of values using Jython and zxJDBC使用 Jython 和 zxJDBC 进行多行值的 SQL INSERT
【发布时间】:2014-05-03 13:50:57
【问题描述】:

我正在使用 com.ziclix.python.sql 包在 Jython 中对 SQL 数据库进行编程。我想知道该包是否在其准备好的 SQL INSERT/UPDATE 语句中支持您传递多行值而不是仅传递一行的语句,以便在一个 INSERT 语句中插入多行。让我解释一下。

这是一个基本的 SQL INSERT 语句:

INSERT INTO Names (FirstName, LastName) VALUES ("John", "Doe");

使用 zxJDBC 准备语句,这很简单:

# Assume cursor object
statement = 'INSERT INTO Names (FirstName, LastName) VALUES (?, ?)'
cursor.execute(statement, ('John', 'Doe'))

但我感兴趣的 INSERT 语句是在其中插入多行值,如下所示:

INSERT INTO Names (FirstName, LastName) VALUES ("John", "Doe"), ("Mary", "Smith");

有没有办法使用准备好的语句来做到这一点?如果可能的话,我宁愿使用准备好的语句来构建 SQL 查询,而不是字符串插值。谢谢。

【问题讨论】:

  • 你有理由不循环执行吗?带有选择的插入呢?
  • 我可以循环执行,但我的理解是每次调用 cursor.execute 代表一个单独的数据库往返。在测试中我一次做 100 行,但在生产中它可能会比这高得多。在对 cursor.execute 的一次调用中插入多个值似乎是一种我不能没有的优化,因为如果我理解正确,那将只是到数据库的一次往返。
  • 您对数据库的访问是正确的。尽管如此,你还是想知道它对你来说到底有多慢。如果尝试在不需要的地方进行优化,您可以编写一些糟糕的代码
  • 如果您按照问题所示创建 sql,通过插值数据,您可以创建一个允许您插入多行的联合。
  • 你是对的,它与多组值差别不大。尽管如此,准备好的语句只是字符串插值。可能您真正想要的是某种延迟执行,但我不确定除了手动构建字符串之外如何做到这一点,正如我们所讨论的那样。太糟糕了,你没有使用 c# 和 Linq。 :) 祝你好运!

标签: python sql database prepared-statement jython


【解决方案1】:

由于zxJDBC实现了PEP 249“Python数据库API规范v2.0”,所以可以使用executemany()方法来完成:

# Assume cursor object
statement = 'INSERT INTO Names (FirstName, LastName) VALUES (?, ?)'
cursor.executemany(statement, (
    ('John', 'Doe'),
    ('Mary', 'Smith'),
    # ...
    )
)

更新:看起来这太慢了,因为 zxJDBC 只是多次调用 execute 而不优化查询。相反,您可以这样做:

from itertools import chain
statement = 'INSERT INTO Names (FirstName, LastName) VALUES {values}'.format(
    values = ','.join('(?, ?)' for _ in input_seq))
input_seq = (
    ('John', 'Doe'),
    ('Mary', 'Smith'),
    # ...
    )
cursor.execute(statement, list(chain(*input_seq)))

确实涉及一些字符串操作,但它保留了参数列表的使用并允许单个数据库往返。

【讨论】:

  • 据我所知,cursor.executemany 对程序员来说是一种便利,但仍会单独往返数据库。请参阅我在上面对 paqogomez 的评论中写的内容。我测试了插入 10,000 行,这是我的应用程序在生产中的负载。 executemany 不比执行快——16.25 秒(在我的机器上)。如果我做一些字符串连接并一次执行它,它需要 0.05 秒。这快了 325 倍。然而,将字符串拼凑在一起需要稍微调整数据,而准备好的语句可以省去我所有的麻烦。
  • 你知道吗,我意识到我现在要求的并不是我一开始就要求的。在我开始得到一些答案之前,我什么也没说优化。如果你知道任何,请告诉我。但是,我觉得我应该将您的答案标记为正确答案。
  • 是的,it looks like you're right。不过,我有一个想法,可以通过一种骇人听闻的方式来获得您想要的东西……
  • 我将您的答案标记为正确答案,因为正如我所说,它回答了我提出的问题。谢谢你。至于“hacky way”,我已经想出了自己的hacky方式。我使用多组值动态构建我的 SQL 语句的值部分(根据 SQL 语法,每组值都括在括号中,并用逗号与后面的组分隔)。这很好用。我只是希望模块本身提供这个。将 Python 对象转换为它们在 SQL 行中的显示方式有点棘手。 (而准备好的语句会为您处理所有这些。)
  • P.S.我没有看到您使用 itertools 进行的更新。我会看看那个。谢谢!
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2013-03-07
  • 2011-03-10
  • 1970-01-01
  • 2021-11-19
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多