通过调用Postgres函数插入记录时如何提交

时间:2017-12-03 04:07:05

标签: python postgresql plsql sqlalchemy

我写了一个函数来将记录插入表person。行ID是串行(自动递增)

CREATE OR REPLACE FUNCTION public.add_person(
    name character varying,
    email character varying,
    level integer,
    company_id integer,
    comp_list integer[])
    RETURNS integer as

$BODY$
declare 
    p_id integer;
begin 
    insert into person (name, email, level, company_id, comp_list, status, insert_ts) values ($1, $2, $3, $4, $5, 'Y', now())
    returning person.person_id into p_id;
    return p_id;
end
$BODY$ LANGUAGE 'plpgsql'

如果我使用sql select * from add_person('xxx', 'xxx@gmail.com', 1, 3, '{1,2}')运行此函数,它会成功插入记录。但是当我使用SQLAlchemy在Python中调用此函数时,记录无法插入。

engine = create_engine(URL(**settings.DATABASE))
session = scoped_session(sessionmaker(bind=engine))
email = 'xxx@gmail.com'
company = 1
level = 3
comp_list = '1,2'
args = "'', '" + email + "', " + str(company) + ", " + str(level) + ", '{" + comp_list + "}'"
statement = "select * from add_person({})".format(args)
session.execute(statement)

用Python构造的语句与我在postgres中运行的命令完全相同。但它并没有像它应该的那样在表中插入记录。完全没有错误消息。 sessionengine配置正确,因为所有其他select查询都有效。

我也注意到即使不能使用python代码插入记录。主键的顺序确实增加了。因为当我在postgres中再次运行该函数时,行ID被跳过。

如果我使用没有提交的SQLAlchemy会话进行插入,行为是相同的。

def add_person(name, email, company, level, comp_list):
    current_ts = datetime.datetime.now()
    p = Person(name = name,
               email = email,
               company_id = company,
               level = level,
               comp_list = comp_list,
               status = 'Y',
               insert_ts = current_ts)
    session.add(p)
    session.flush()
    return p.person_id

如果我运行上面的Python方法,person_id会递增,但不会插入任何记录。只有当我将session.flush更改为以下内容时,才能正确插入记录。

    session.add(p)
    session.commit()
    session.refresh(p)
    print(p.person_id)
    return p.person_id

调用plsql函数时提交插入的正确方法是什么?

1 个答案:

答案 0 :(得分:2)

除非您将autocommit连接设置为True,否则您需要调用会话的commit()功能。

文档:http://docs.sqlalchemy.org/en/latest/orm/session_basics.html#when-do-i-construct-a-session-when-do-i-commit-it-and-when-do-i-close-it

即使没有提交,person_id递增的原因是因为它正在使用序列 - 您明确创建的序列或者在您将列类型定义为SERIAL时为您创建的序列(或类似) )。该序列将在有或没有提交的情况下递增,并且不依赖于在表中成功插入记录。

请注意,仅涉及SELECT的语句不需要调用提交。