2017-12-03 14 views
0

레코드를 테이블 person에 삽입하는 함수를 작성했습니다. 행 ID는 내가 SQL select * from add_person('xxx', '[email protected]', 1, 3, '{1,2}')이 기능을 실행하면 성공적으로 레코드를 삽입 (자동 증가)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' 

시리얼입니다. 그러나 SQLAlchemy를 사용하여 파이썬에서이 함수를 호출하면 레코드를 삽입 할 수 없습니다. 파이썬으로 구성

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) 

성명은 정확하게 내가 포스트 그레스에서 실행되는 명령과 동일합니다. 그러나 그것은 그것이 예정되어있는 것처럼 테이블에 레코드를 삽입하지 않았습니다. 오류 메시지가 전혀 없습니다. 다른 모든 select 쿼리가 작동하기 때문에 session, engine이 올바르게 구성되었습니다.

파이썬 코드를 사용하여 레코드를 삽입 할 수없는 경우에도주의를 기울였습니다. 기본 키의 순서가 증가했습니다. 포스트 그레스에서 함수를 다시 실행할 때 행 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 

내가 파이썬 위의 방법, person_id 단위를 실행하지만 레코드가 삽입되지 않은 경우. session.flush을 다음으로 변경 한 경우에만 레코드가 올바르게 삽입됩니다.

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

plsql 함수를 호출 할 때 삽입을 커밋하는 올바른 방법은 무엇입니까?

+1

[트랜잭션 제어]를 참조하십시오. (http://initd.org/psycopg/docs/usage.html#transactions-control) – klin

+0

값을 전달할 때 문자열 형식을 사용하지 마십시오. * 검색어로 이것이 placeholder/bindparams가하는 것입니다. "how"에 대해서는 http://docs.sqlalchemy.org/en/latest/core/tutorial.html#using-textual-sql을 읽고 "why"에 대해서는 https://xkcd.com/327/을 읽으십시오. –

+1

여기에 텍스트 SQL이 필요하지 않습니다. 함수 제네릭을 사용하면'execute (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만을 포함하는 명령문에는 커밋 호출이 필요하지 않습니다.