2013-01-17 3 views
9

SQLAlchemy를 통해 대량 행을 삽입/업데이트해야합니다. 삽입 된 행을 가져옵니다. SQLAlchemy : 자동 닫기 방지

나는 session.execute와 함께 할 것을 시도 :

>>> posts = db.session.execute(Post.__table__.insert(), [{'title': 'dfghdfg', 'content': 'sdfgsdf', 'topic': topic}]*2) 
>>> posts.fetchall() 

ResourceClosedError      Traceback (most recent call last) 

그리고 엔진 :

In [17]: conn = db.engine.connect() 

In [18]: result = conn.execute(Post.__table__.insert(), [{'title': 'title', 'content': 'content', 'topic': topic}]*2) 

In [19]: print result.fetchall() 
ResourceClosedError: This result object does not return rows. It has been closed automatically. 

같은 응답은 객체가 자동으로 종료 된 것입니다. 그것을 막는 방법?

답변

8

첫 번째 대답은 "자동 닫기 방지"입니다.

SQLAlchemy는 insert를 사용하여 DBAPI execute() 또는 executemany()를 실행하고 select 쿼리를 수행하지 않습니다. 그래서 예외는 예상되는 동작입니다. 삽입 쿼리 실행 후 반환 된 ResultProxy 개체는 .fetchall()을 수행 할 수없는 DB-API 커서를 래핑합니다. .fetchall()이 실패하면 ResultProxy는 사용자에게 예외를 반환합니다.

삽입/업데이트/삭제 작업 후에 얻을 수있는 유일한 정보는 영향을받는 행 수 또는 자동 증가 후 기본 키 값입니다 (데이터베이스 및 데이터베이스 드라이버에 따라 다름).

  • 을 .lastrowid

    • .inserted_primary_key
    • .last_inserted_params() : 당신의 목표는 이런 종류의 정보를 수신하는 경우

      는 같은 ResultProxy methods and attributes을 확인 고려 두 번째 대답 - "벌크 삽입/업데이트를 수행하고 결과를 얻는 방법 행 ".

      DBAPI를 사용하여 단일 삽입 쿼리를 수행하는 동안 삽입 된 행을로드 할 수있는 방법이 없습니다. 대량 삽입/업데이트를 수행하기 위해 사용하는 SQLAlchemy SQL Expression API는 이러한 기능을 제공하지 않습니다. SQLAlchemy는 DBAPI executemany() 호출을 실행하고 드라이버 구현을 사용합니다. 자세한 내용은 this section of documentation을 참조하십시오.

      해결 방법 모든 레코드가 고유 한 방식으로 레코드를 식별하는 열 값의 조합 인 레코드를 식별하는 자연스러운 키를 갖는 방식으로 테이블을 디자인하는 것이 해결책 일 것입니다. 따라서 insert/update/select 쿼리는 하나의 레코드를 대상으로 할 수 있습니다. 먼저 일괄 삽입/업데이트를 수행 한 다음 Natual Key를 사용하여 select 쿼리를 수행 할 수 있습니다. 따라서 자동 증가 기본 키 값을 알 필요가 없습니다.

      다른 옵션 : 개체를 만들 때 SQLAlchemy Object Relational API을 사용할 수 있습니다. 그러면 SQLAlchemy가 executemany를 사용하여 하나의 쿼리를 수행하도록 삽입을 최적화하려고 시도 할 수 있습니다. 오라클 DB를 사용하면서 저에게 도움이되었습니다. 즉시 사용 가능한 업데이트 최적화는 없습니다. 효율적인 대량 업데이트 아이디어를 얻으려면 this SO question을 확인하십시오.

  • +2

    감사합니다. – I159