我在Python3.8、PostgreSQL 12和PyGreSQL 5.2.2上使用CentOS-6。
对于较旧的版本,我有一个如下所示的函数。当时,如果行不存在,update将引发异常,因此在出现异常时,我将插入数据行。
import pg
db = pg.DB(myDatabaseName, myport)
try:
db.update(tableName, None, **rowData)
except:
db.insert(tableName, None, **rowData)在我现在使用的版本中,如果行不存在,更新不会引发异常,因此我的代码不再正常工作。我正在尝试使用upsert来替换该功能,但遇到了问题。
我的表有50列。名为phy的1列是主键。
我认为下面的upsert命令会更新我在rowData变量中传递的列的值,而不会影响其他列。在这个主键没有一行数据的情况下,它将插入新的一行数据。
rowData = {'phy': 1234, 'col2': 'test', 'col3': 'test'}
db.upsert(tableName, rowData)upsert方法将更新表中的每一列。它执行的命令如下所示:
INSERT INTO tableName AS included ('phy', 'col2', col3') VALUES (1234, 'test', 'test) ON CONFLICT (phy) DO update set "col4" = excluded."col4", "col5"=excluded."col5" etc with all 50 columns listed here有没有办法将upsert方法配置为只更新传入的列的值?如果不是,那么替换原始更新或插入功能的最佳方式是什么?
如有任何帮助,我们不胜感激!
发布于 2021-06-11 20:25:51
关于你的第一个代码片段,如果你反其道而行之,它应该可以工作:
try:
db.insert(tableName, None, **rowData)
except pg.IntegrityError:
db.update(tableName, None, **rowData)您还可以简化此操作:
try:
db.insert(tableName, rowData)
except pg.IntegrityError:
db.update(tableName, rowData)也许这与使用OID进行更新的旧PostgreSQL版本的行为有所不同。
关于upsert特性,我认为你是对的-在字典没有包含所有列的情况下,它不会像预期的那样工作。我已经提交了一份issue,并提出了改进建议。
作为一种变通方法,在这个问题得到解决之前,您可以通过upsert()方法的关键字显式地声明哪些列应该更新。所以你可以这样做:
rowData = {'phy': 1235, 'col2': 'test2', 'col3': 'test3'}
kw = {n: n in rowData for n in db.get_attnames(tableName)}
db.upsert(tableName, rowData, **kw)也就是说,您传递一个字典,该字典具有不属于指定rowData的列的False值。
https://stackoverflow.com/questions/67926936
复制相似问题