psycopg2 - 具有多个插入语句的函数未提交

时间:2015-11-06 19:16:48

标签: python postgresql psycopg2

我有以下带有2个插入语句的PosgreSQL函数:

CREATE OR REPLACE FUNCTION create_user(
    _username character varying,
    _email character varying,
    _password character varying,
    _first_name character varying,
    _middle_initial character,
    _last_name character varying,
    _title character varying,
    _enabled boolean,
    _company_id integer,
    _created_by integer,
    _superuser boolean)
  RETURNS UserAccount AS
$BODY$DECLARE
    result UserAccount;
BEGIN
    INSERT INTO UserAccount
        (username, email, password, first_name, middle_initial,
        last_name, title, enabled, created_by, superuser)
    VALUES (_username, _email, _password, _first_name,_middle_initial,
        _last_name, _title, _enabled, _created_by, _superuser)
    RETURNING * INTO result;

    INSERT INTO UserCompany (user_id, company_id)
    VALUES (result.id, _company_id);

    RETURN result;
END;$BODY$
  LANGUAGE plpgsql VOLATILE STRICT;

通过PGAdmin执行SELECT * FROM create_user(..._)按预期工作并返回新的UserAccount行。

我的Python代码如下:

conn = psycopg2.connect(app.config.get('POSTGRES_URI'))
cursor = conn.cursor()

# Some prep of variables...

cursor.execute("""
    SELECT
        id, username, email, first_name, middle_initial, last_name, last_login, title, failed_attempts, enabled, created_by, superuser
    FROM create_user(%s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s)""", (
        username, email, str(hashed_password), first_name, middle_initial, last_name,
        title, enabled, company_id, created_by, superuser
    ))

conn.commit()

user = dict(zip([x[0] for x in g.db.description], g.db.fetchone()))

cursor.close()
conn.close()

return user

这将返回值的所有空值,而不是提交插入。如果我从函数中删除第二个INSERT语句,它将按预期工作。我尝试了conn.autocommit = Trueconn.set_isolation_level(0),并使用了cursor.callproc(...)方法。仍然不起作用。我现在错过了什么,或者这是psycopg2的问题吗?

编辑 - 解决方案(facepalm):

我发现问题是函数的STRICT子句。与pscyopg2无关。感觉现在问这个问题。我正在向函数传递一个空值,当然,这是当传递空值时STRICT应该做什么......没有。

3 个答案:

答案 0 :(得分:0)

您不应该在Python脚本中提交您的select语句。提交应该在您的PosgreSQL函数中进行。尝试抛出一个提交;在RETURN线以上。

答案 1 :(得分:0)

解决方案(facepalm):

我发现问题是函数的STRICT子句。与pscyopg2无关。感觉现在问这个问题。我正在向函数传递一个空值,当然,这是当传递空值时STRICT应该做什么......没有。

答案 2 :(得分:0)

适合我:

create table UserAccount (
    id serial primary key, username text
);
create table UserCompany (
    user_id integer primary key,
    company_id integer
);
create or replace function create_user(
    _username character varying,
    _company_id integer
) returns UserAccount as $body$
declare
    result UserAccount;
begin
    insert into UserAccount (username)
    values (_username)
    returning * into result;

    insert into UserCompany (user_id, company_id)
    values (result.id, _company_id);

    return result;
end;
$body$ language plpgsql volatile strict;

Python代码

from psycopg2 import connect
con = connect('dbname=cpn')
curs = con.cursor()
curs.execute('''
    select * from create_user(%s, %s);
''', ('john', 2))
con.commit()
user = curs.fetchone()
print user
con.close()

返回

(2, 'john')