[python] SQLAlchemy : 엔진, 연결 및 세션 차이

: 나는 SQLAlchemy의를 사용하고 적어도 세 기관이있다 engine, session그리고 connection가지고있는, execute예를 들어 내가 모든 레코드를 선택합니다 그렇다면, 방법을 table나는이 작업을 수행 할 수 있습니다

engine.execute(select([table])).fetchall()

connection.execute(select([table])).fetchall()

심지어 이것

session.execute(select([table])).fetchall()

-결과는 동일합니다.

내가 이해하는 것처럼 누군가 누군가 engine.execute그것을 사용 하면 create connection을 열고 session(Alchemy가 처리합니다) 쿼리를 실행합니다. 그러나 이러한 작업을 수행하는이 세 가지 방법 사이에 전 세계적 차이가 있습니까?



답변

한 줄 개요 :

의 동작은 execute()모든 경우에 동일하지만, 그들은 3 개 가지 방법에 Engine, Connection그리고 Session클래스.

정확히 무엇입니까 execute():

execute()우리의 행동을 이해하려면 Executable수업 을 살펴 봐야합니다 . Executableselect (), delete (), update (), insert (), text ()를 포함한 모든 “statement”유형의 객체에 대한 수퍼 클래스입니다. 가능한 가장 간단한 단어로, ExecutableSQLAlchemy에서 지원되는 SQL 식 구문입니다.

모든 경우에이 execute()메소드는 SQL 텍스트 또는 생성 된 SQL 표현식, 즉 SQLAlchemy에서 지원되는 다양한 SQL 표현식 구성 중 하나를 취하여 쿼리 결과를 리턴합니다 ( ResultProxya- DB-API행 오브젝트에 쉽게 액세스 할 수 있도록 커서 오브젝트 랩핑 ).


더 명확하게하기 위해 (개념적 설명만을 위해 권장되는 접근법은 아님) :

Engine.execute()(연결없는 실행) 외에도 Connection.execute(), 및 모든 구문 Session.execute()에서 execute()직접 사용할 수도 있습니다 Executable. 이 Executable클래스에는 자체 구현이 있습니다. execute()공식 문서에 따라 수행 한 작업에 대한 한 줄 설명 execute()은 ” 컴파일 및 실행Executable “입니다. 이 경우 객체 또는 객체 (암시 적으로 객체 를 가져옴 Executable)와 (SQL 표현식 구성) 을 명시 적으로 바인딩해야 하므로 를 실행할 위치를 알 수 있습니다 .ConnectionEngineConnectionexecute()SQL

다음 예제는이를 잘 보여줍니다. 아래와 같은 테이블이 있습니다.

from sqlalchemy import MetaData, Table, Column, Integer

meta = MetaData()
users_table = Table('users', meta,
    Column('id', Integer, primary_key=True),
    Column('name', String(50)))

명시 적 실행,Connection.execute()-SQL 텍스트 또는 생성 된 SQL 표현식을 다음 execute()메소드에 전달합니다 Connection.

engine = create_engine('sqlite:///file.db')
connection = engine.connect()
result = connection.execute(users_table.select())
for row in result:
    # ....
connection.close()

명시 적 비 연결 실행 (Engine.execute(), SQL 텍스트 또는 생성 된 SQL 표현식 execute()을 Engine 메소드에 직접 전달) :

engine = create_engine('sqlite:///file.db')
result = engine.execute(users_table.select())
for row in result:
    # ....
result.close()

암시 적 실행Executable.execute(), 또한 연결이 없으며execute()메소드를 호출합니다. 즉 , 표현식 구문 (의 인스턴스 ) 자체 에서 직접 메소드를 Executable호출 합니다.execute()SQLExecutable

engine = create_engine('sqlite:///file.db')
meta.bind = engine
result = users_table.select().execute()
for row in result:
    # ....
result.close()

참고 : 설명을 위해 암시 적 실행 예제를 명시했습니다.이 실행 방법은 문서 별로 권장하지 않습니다 .

“암시 적 실행”은 매우 오래된 사용 패턴으로 대부분의 경우 도움보다 혼란스럽고 사용이 권장되지 않습니다. 두 패턴 모두 나중에 응용 프로그램 디자인에서 편리한 “바로 가기”를 과도하게 사용하는 것으로 보이며 나중에 문제가 발생합니다.


당신의 질문:

누군가 engine.execute를 사용하면 연결을 만들고 세션을 열고 (Alchemy가 관심을 갖습니다) 쿼리를 실행합니다.

당신은 “누군가 사용하면 부분 맞아요 engine.execute이 생성 connection하지만 대한은”개방 ” session(연금술 당신을 위해에 대한 염려)하고 실행하는 쿼리를”- 사용 Engine.execute()하고 Connection.execute()(거의) 하나 같은 일이 공식에서, Connection오브젝트가 내재적으로 작성됩니다 나중에는 명시 적으로 인스턴스화합니다. 이 경우 실제로 일어나는 일은 다음과 같습니다.

`Engine` object (instantiated via `create_engine()`) -> `Connection` object (instantiated via `engine_instance.connect()`) -> `connection.execute({*SQL expression*})`

그러나 이러한 작업을 수행하는 세 가지 방법 간에는 전 세계적으로 다른 점이 있습니까?

DB 계층에서 정확히 같은 것입니다. 모두 SQL (텍스트 표현식 또는 다양한 SQL 표현식 구성)을 실행하고 있습니다. 응용 프로그램의 관점에서 두 가지 옵션이 있습니다.

  • 직접 실행- Engine.execute()또는Connection.execute()
  • 사용 sessions– 효율적 개의 단위 작업으로 트랜잭션을 처리, 쉽게를 통해 session.add(), session.rollback(), session.commit(), session.close(). ORM 즉 매핑 된 테이블의 경우 DB와 상호 작용하는 방법입니다. 단일 요청 중에 이미 액세스했거나 새로 생성 / 추가 된 객체를 즉시 가져올 수 있도록 identity_map 을 제공합니다 .

Session.execute()궁극적으로 Connection.execute()SQL 문을 실행하기 위해 명령문 실행 방법을 사용 합니다. Session응용 프로그램이 데이터베이스와 상호 작용하기 위해 오브젝트를 사용하는 것이 SQLAlchemy ORM의 권장 방법입니다.

문서 에서 발췌 :

SQLAlchemy ORM을 사용할 때 이러한 오브젝트는 일반적으로 액세스되지 않습니다. 대신 Session 개체는 데이터베이스에 대한 인터페이스로 사용됩니다. 그러나 ORM의 상위 레벨 관리 서비스를 사용하지 않고 텍스트 SQL 문 및 / 또는 SQL 표현식 구성을 직접 사용하도록 빌드 된 응용 프로그램의 경우 엔진 및 연결이 왕성한 (그리고 여왕입니까?)입니다.


답변

Nabeel의 답변 은 많은 세부 사항을 다루고 도움이되지만 따르기가 혼란 스럽습니다. 이것이 현재이 문제에 대한 첫 번째 Google 결과이므로이 질문을 발견 한 미래의 사람들을 위해 이해하고 있습니다.

.execute () 실행

OP와 Nabell Ahmed는 plain을 실행할 때 SELECT * FROM tablename제공된 결과에 차이가 없음을 지적합니다.

이 세 개체 사이의 차이는 그 상황에 따라 중요 해지고 않는 SELECT문이 또는 더 일반적으로, 당신이 원하는 때와 같은 다른 것들에 사용되는 INSERT, DELETE

엔진, 연결, 세션을 일반적으로 사용하는 경우

  • 엔진 은 SQLAlchemy에서 사용하는 가장 낮은 수준의 개체입니다. 그것은 연결 풀 유지 관리 응용 프로그램이 데이터베이스에 이야기해야 할 때마다 사용할 수 있습니다. .execute()먼저 호출 conn = engine.connect(close_with_result=True)하고 그 다음에 편리한 방법입니다 conn.execute(). close_with_result 매개 변수는 연결이 자동으로 종료되었음을 의미합니다. (저는 소스 코드를 약간 해석하고 있지만 본질적으로 사실입니다). 편집 : 다음은 engine.execute의 소스 코드입니다.

    엔진을 사용하여 원시 SQL을 실행할 수 있습니다.

    result = engine.execute('SELECT * FROM tablename;')
    #what engine.execute() is doing under the hood
    conn = engine.connect(close_with_result=True)
    result = conn.execute('SELECT * FROM tablename;')
    
    #after you iterate over the results, the result and connection get closed
    for row in result:
        print(result['columnname']
    
    #or you can explicitly close the result, which also closes the connection
    result.close()

    이것은 기본 사용법 의 문서에서 다룹니다 .

  • 연결 은 (위에서 보았 듯이) 실제로 SQL 쿼리를 실행하는 작업입니다. 연결 속성이 닫힐 때 등의 속성에 대한 제어를 강화할 때마다이 작업을 수행해야합니다. 예를 들어, 매우 중요한 예로는 Transaction 을 사용하여 데이터베이스에 변경 사항을 커밋 할시기를 결정할 수 있습니다. 정상적인 사용에서는 변경 사항이 자동 커밋됩니다. 트랜잭션을 사용하면 (예를 들어) 여러 가지 다른 SQL 문을 실행할 수 있으며 그 중 하나에 문제가 있으면 한 번에 모든 변경 내용을 취소 할 수 있습니다.

    connection = engine.connect()
    trans = connection.begin()
    try:
        connection.execute("INSERT INTO films VALUES ('Comedy', '82 minutes');")
        connection.execute("INSERT INTO datalog VALUES ('added a comedy');")
        trans.commit()
    except:
        trans.rollback()
        raise

    이렇게하면 데이터 로그 테이블 생성을 잊어 버린 것처럼 하나의 변경이 실패하면 두 변경 사항을 모두 취소 할 수 있습니다.

    따라서 원시 SQL 코드를 실행하고 제어가 필요한 경우 연결을 사용하십시오.

  • 세션 은 SQLAlchemy의 ORM (Object Relationship Management) 측면에 사용됩니다 (실제로 가져 오는 방법에서 볼 수 있음 from sqlalchemy.orm import sessionmaker). 이들은 자동 생성 된 SQL 문을 실행하기 위해 연결 및 트랜잭션을 사용합니다. .execute()세션이 바인딩 된 모든 항목 (일반적으로 엔진이지만 연결될 수 있음)으로 전달되는 편리한 기능입니다.

    ORM 기능을 사용하는 경우 세션을 사용하십시오. 객체에 바인딩되지 않은 직선 SQL 쿼리 만 수행하는 경우 연결을 직접 사용하는 것이 좋습니다.


답변

다음은 GRANT와 같은 DCL (Data Control Language)을 실행하는 예입니다.

def grantAccess(db, tb, user):
  import sqlalchemy as SA
  import psycopg2

  url = "{d}+{driver}://{u}:{p}@{h}:{port}/{db}".\
            format(d="redshift",
            driver='psycopg2',
            u=username,
            p=password,
            h=host,
            port=port,
            db=db)
  engine = SA.create_engine(url)
  cnn = engine.connect()
  trans = cnn.begin()
  strSQL = "GRANT SELECT on table " + tb + " to " + user + " ;"
  try:
      cnn.execute(strSQL)
      trans.commit()
  except:
      trans.rollback()
      raise


답변