我有多处理应用程序,需要upsert(插入,如果存在更新)功能。在

我决定使用触发器解决方案来接近upsert。(为每个名为is_upsert的启用upsert的表添加额外的列,在触发器检查此字段时,如果为false,则执行正常插入,但如果为true,则执行upsert逻辑-尝试更新,如果由于记录不存在而失败,则尝试插入)。在

触发逻辑如下:CREATE OR REPLACE FUNCTION upsert_trigger_function_{table}()

RETURNS TRIGGER AS $upsert_trigger_function$

DECLARE

row record;

BEGIN

RAISE NOTICE 'upsert trigger fired, upsert is %%', NEW.{upsert_column};

IF NEW.{upsert_column} THEN

NEW.{upsert_column} := false;

LOOP

UPDATE {table} SET

{update_set}

WHERE

{update_where}

;

IF found THEN

RETURN NULL;

END IF;

BEGIN

INSERT INTO {table} SELECT NEW.*;

RETURN NULL;

EXCEPTION WHEN unique_violation THEN

-- loop

END;

END LOOP;

RETURN NULL;

ELSE

RETURN NEW;

END IF;

END;

$upsert_trigger_function$ LANGUAGE plpgsql;

测试对象(add\u upsert只需安装上述触发器):

^{pr2}$

测试脚本from sqlalchemy.engine import create_engine

from pipelines.settings_proxy import TEST_DB

from sqlalchemy.orm.session import sessionmaker

from test_pipelines.test_persistence.mock_items import SimpleItem

from test_pipelines.test_persistence.helpers import random_simple_item

def main():

engine = create_engine(TEST_DB)

values = random_simple_item(_upsert=True)

session = sessionmaker(engine)()

si = SimpleItem(**values)

session.add(si)

session.commit()

si = SimpleItem(**values)

si.price = 1

session.merge(si)

session.commit()

它在使用SQL statesments时可以正常工作,但是当我将它与SQLAlchemy ORM add object一起使用时,它就有了Traceback (most recent call last):

File "pipelines/persistence/experiment_with_upsert_field.py", line 59, in

main()

File "pipelines/persistence/experiment_with_upsert_field.py", line 27, in main

session.commit()

File "/home/sebastian/local/virtualenvs/perception/lib/python3.4/site-packages/sqlalchemy/orm/session.py", line 801, in commit

self.transaction.commit()

File "/home/sebastian/local/virtualenvs/perception/lib/python3.4/site-packages/sqlalchemy/orm/session.py", line 392, in commit

self._prepare_impl()

File "/home/sebastian/local/virtualenvs/perception/lib/python3.4/site-packages/sqlalchemy/orm/session.py", line 372, in _prepare_impl

self.session.flush()

File "/home/sebastian/local/virtualenvs/perception/lib/python3.4/site-packages/sqlalchemy/orm/session.py", line 2019, in flush

self._flush(objects)

File "/home/sebastian/local/virtualenvs/perception/lib/python3.4/site-packages/sqlalchemy/orm/session.py", line 2137, in _flush

transaction.rollback(_capture_exception=True)

File "/home/sebastian/local/virtualenvs/perception/lib/python3.4/site-packages/sqlalchemy/util/langhelpers.py", line 60, in __exit__

compat.reraise(exc_type, exc_value, exc_tb)

File "/home/sebastian/local/virtualenvs/perception/lib/python3.4/site-packages/sqlalchemy/util/compat.py", line 184, in reraise

raise value

File "/home/sebastian/local/virtualenvs/perception/lib/python3.4/site-packages/sqlalchemy/orm/session.py", line 2101, in _flush

flush_context.execute()

File "/home/sebastian/local/virtualenvs/perception/lib/python3.4/site-packages/sqlalchemy/orm/unitofwork.py", line 373, in execute

rec.execute(self)

File "/home/sebastian/local/virtualenvs/perception/lib/python3.4/site-packages/sqlalchemy/orm/unitofwork.py", line 532, in execute

uow

File "/home/sebastian/local/virtualenvs/perception/lib/python3.4/site-packages/sqlalchemy/orm/persistence.py", line 174, in save_obj

mapper, table, insert)

File "/home/sebastian/local/virtualenvs/perception/lib/python3.4/site-packages/sqlalchemy/orm/persistence.py", line 800, in _emit_insert_statements

execute(statement, params)

File "/home/sebastian/local/virtualenvs/perception/lib/python3.4/site-packages/sqlalchemy/engine/base.py", line 914, in execute

return meth(self, multiparams, params)

File "/home/sebastian/local/virtualenvs/perception/lib/python3.4/site-packages/sqlalchemy/sql/elements.py", line 323, in _execute_on_connection

return connection._execute_clauseelement(self, multiparams, params)

File "/home/sebastian/local/virtualenvs/perception/lib/python3.4/site-packages/sqlalchemy/engine/base.py", line 1010, in _execute_clauseelement

compiled_sql, distilled_params

File "/home/sebastian/local/virtualenvs/perception/lib/python3.4/site-packages/sqlalchemy/engine/base.py", line 1159, in _execute_context

result = context._setup_crud_result_proxy()

File "/home/sebastian/local/virtualenvs/perception/lib/python3.4/site-packages/sqlalchemy/engine/default.py", line 828, in _setup_crud_result_proxy

self._setup_ins_pk_from_implicit_returning(row)

File "/home/sebastian/local/virtualenvs/perception/lib/python3.4/site-packages/sqlalchemy/engine/default.py", line 893, in _setup_ins_pk_from_implicit_returning

for col in table.primary_key

File "/home/sebastian/local/virtualenvs/perception/lib/python3.4/site-packages/sqlalchemy/engine/default.py", line 891, in

for col, value in [

TypeError: 'NoneType' object is not subscriptable

在深处升起sqlalchemy.engine.default. 我确信这是因为我的触发器在执行UPSERT时返回NULL,而SQLAlchemy尝试使用RETURNING语句传播带有插入ID的对象。它显然失败了,因为它不可能从它的从属INSERT/UPDATE在触发器中获取正确的ID,同时阻止正常的正常插入。在

请注意,我已经将upsert作为一个特殊函数进行了测试,但这对我来说并不适用,因为我牺牲了SQLAlchemy在更新复杂项(那些与其他项有关系的项)方面的帮助。在

所以我的问题是:如何告诉SQLAlchemy避免加载插入的对象ID?

oracle 触发器 upsert,如何使SQLAlchemy insert与Postgres多处理proof upsert触发器一起工作?...相关推荐

  1. 视频教程-赵强老师:Oracle数据库从10g到11g(5)过程、函数和触发器-Oracle

    赵强老师:Oracle数据库从10g到11g(5)过程.函数和触发器 毕业于清华大学,拥有超过13年的工作经验. Oracle认证讲师,拥有6年以上授课经验.精通Oracle数据库.中间(Weblog ...

  2. mysql 触发器 运算符_mysql三元运算,上下连表,视图,触发器,存储过程,事务等不常用方法...

    1 MySql中的三元运算符有两种方法: 1.case when 条件 then (条件为true时执行) else(条件为false时执行) end;/*end不可少*/ 2.select *,if ...

  3. SQL Server 触发器( trigger ) ------- 用例详解( 你需要举一反三的触发器实用方法都在这了 )

    trigger 导航专用 第一部分 1. 概述 ① 触发器的特点 ② 触发器的作用 ③ 触发器的分类 ④ DML 触发器的分类 第二部分 实现 1. 触发器的创建 ① insert 触发器的创建 ② ...

  4. 一起Oracle回收站过大引发的insert逻辑读过高故障

    某客户CPU暴增,且居高不下,通过gv$session发现一条insert造成大量的阻塞和等待,产生大量row chache lock.gc buffer busy acquire.read by o ...

  5. Oracle NoLogging Append 方式减少批量insert的redo_size

    业务处理中,很多时候使用实表临时表处理中间结果,而实表的Insert操作缺省会记录redo log,针对此问题收集相关测试总结信息如下: [转] 常见dml.ddl语句使用nologging选项所生成 ...

  6. oracle数据库【表复制】insert into select from跟create table as select * from 两种表复制语句区别...

    create table  as select * from和insert into select from两种表复制语句区别 create table targer_table as select ...

  7. oracle10g执行insert,oracle 10g 增强审计。表insert 及bind values

    oracle 10g之前,可以审计对表的操作,但不能记录操作时的各个列的值.在10g中,已经可以审核并监控到具体的sql语句及内容了. 要求 10g以后的版本. alter system set au ...

  8. Oracle入门(十四.22)之创建DDL和数据库事件触发器

    一.什么是DDL和数据库事件触发器? DDL语句触发DDL触发器:CREATE,ALTER或DROP. 数据库事件触发器由数据库中的非SQL事件触发,例如: •用户连接到数据库或与数据库断开连接. • ...

  9. url oracle default schema,oracle @Table中使用schema时insert报错

    第一部分 测试情况如下: maven修改 com.alibaba druid 1.1.10 实体类 @Table(name = "dpcenter.xeuser") public ...

最新文章

  1. iOS点击空白收回键盘
  2. python:pandas之read_csv
  3. 生成JSON数据--官方方法
  4. php mysql 分组 分页_简单的PHP+Mysql实现分页
  5. CodeForces 359D (数论+二分+ST算法)
  6. iOS开发——高级篇——iOS开发之网络安全密码学
  7. leetcode刷题日记-472. 连接词
  8. 约瑟夫环问题 poj 1012 poj 2244
  9. matlab按图像边缘抠图_Ps最全十大抠图方法都在这,最后一种万能「值得收藏」...
  10. android foobar wifi,foobar2000安卓
  11. Unity3d是目前主流的游戏开发引擎
  12. js对联广告,顶部浮动广告,固定位置广告插件
  13. 基础笔记(三):网络协议之Tcp、Http
  14. 微信开放平台申请方法与用途
  15. 如何拆分PDF成单页?这三个方法分享给你
  16. java批量下载图片并打包成zip文件
  17. 【C语言】【结构体】复数类型加减乘除的实现
  18. word中的神奇的“Alt + X”
  19. ServiceNow对实施IT服务管理的七个经验和成功实践
  20. [openEuler 21.9] 安装中文输入法、以及字体变成繁体切换

热门文章

  1. Python中numpy中tile和repeat用法和区别
  2. Python中sort与sorted函数
  3. mysql教程or怎么用_MySQL中or语句用法示例
  4. GDB怎么调试使用.sh(shell脚本)启动的程序?(未完成,待测试)
  5. Intel Realsense D435 如何通过摄像头序列号获取指定摄像头的帧集对?
  6. python 用matplotlib.pyplot画(绘制)图表时中文显示不出来怎么办?
  7. 数据集增广 之 多个图片贴到一张图上,以及生成相应的json文件
  8. Half of Same 思维,模拟,调试
  9. php不用密码登录,使用散列密码登录PHP
  10. Spring cloud gateway的自定义异常响应