调用存储函数或过程不会插入并保留更改

时间:2018-07-27 16:19:37

标签: python database postgresql sqlalchemy

所以我对使用SQLAlchemy和PostgreSQL的这种奇怪行为感到非常困惑。假设我有一张桌子:

create table staging.my_table( 
  id integer DEFAULT nextval(...),
  name text,
  ...
);

和一个存储的函数:

create or replace function staging.test()
  returns void
  language plpgsql
  as $function$
begin    
   insert into staging.my_table (name) values ('yay insert');
end;
$function$;

我现在想做的是使用SQLAlchemy在Python中调用此函数,如下所示:

from sqlalchemy import create_engine

engine = create_engine('postgresql+psycopg2://foo:bar@localhost:5432/baz')
engine.execute('select staging.test()')

当我运行此Python代码时,数据库中什么也没有插入。这很奇怪,因为当我将函数调用替换为select 1并向其中添加.fetchall()时,它会被执行,并且在打印时会在控制台中看到结果。

假设我两次运行此代码,但没有任何反应,但是代码运行成功,没有错误。 如果我现在切换到数据库并运行select staging.test();并选择my_table,则会得到:id: 3; name: yay insert

因此,这意味着当我运行Python文件时,序列实际上正在增加,但表中没有数据

我在做什么错?我想念什么吗?我用谷歌搜索,但没有找到任何东西。

1 个答案:

答案 0 :(得分:0)

此特定用例在"Understanding Autocommit"中被选中:

  

使用Connection.execution_options()ConnectionEngine上提供的生成Executable方法并使用“ autocommit”标志,可以完全控制“自动提交”行为打开或关闭选定范围的自动提交。例如,表示提交的存储过程的text()构造可能会使用它,以便SELECT语句将发出COMMIT:

engine.execute(text("SELECT my_mutating_procedure()").execution_options(autocommit=True))

SQLAlchemy自动提交检测数据更改操作的方式是,它将语句与模式匹配,以查找诸如UPDATE,DELETE之类的内容。它无法检测存储的功能/过程是否执行了突变,因此提供了对自动提交的显式控制。

即使因为nextval() and setval() calls are never rolled back而失败,该序列也会递增。