2017-12-03 261 views
0

我寫了一個函數將記錄插入表person。行ID是串行(自動遞增)如何通過調用Postgres函數插入記錄時提交

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', '[email protected]', 1, 3, '{1,2}')這個功能,它成功地插入一條記錄。但是,當我使用SQLAlchemy在Python中調用此函數時,無法插入記錄。

engine = create_engine(URL(**settings.DATABASE)) 
session = scoped_session(sessionmaker(bind=engine)) 
email = '[email protected]' 
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中運行的命令完全相同。但它並沒有像表中那樣插入記錄。根本沒有錯誤信息。 session,engine配置正確,因爲所有其他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

嘗試'conn.autocommit = True'請參閱[事務控制。](http://initd.org/psycopg/docs/usage.html#transactions-control) – klin

+0

請*不要使用字符串格式*來傳遞值查詢。這就是佔位符/綁定對象的用途。閱讀http://docs.sqlalchemy.org/en/latest/core/tutorial.html#using-textual-sql查看「how」和https://xkcd.com/327/查看「why」。 –

+1

這裏甚至不需要文本SQL。函數泛型允許你執行'func.add_person('',email,company,level,comp_list.split(','))。select())'。請注意,您可以並應該將comp_list作爲一個列表。 –

回答

1

除非您有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的語句不需要調用提交。

相關問題