Podsumowanie jednowierszowe:
Zachowanie execute()jest taka sama we wszystkich przypadkach, ale są 3 różne sposoby, w Engine, Connectioni Sessionzajęcia.
Co to dokładnie jest execute():
Aby zrozumieć zachowanie execute(), musimy przyjrzeć się Executableklasie. Executablejest nadklasą dla wszystkich typów obiektów typu „instrukcja”, w tym select (), delete (), update (), insert (), text () - najprościej mówiąc, Executablejest to konstrukcja wyrażenia SQL obsługiwana w SQLAlchemy.
We wszystkich przypadkach execute()metoda przyjmuje tekst SQL lub skonstruowane wyrażenie SQL, tj. Dowolną z różnych konstrukcji wyrażeń SQL obsługiwanych w SQLAlchemy i zwraca wyniki zapytania (a ResultProxy- Zawija DB-APIobiekt kursora, aby zapewnić łatwiejszy dostęp do kolumn wiersza).
Aby wyjaśnić to dalej (tylko w celu wyjaśnienia pojęciowego, a nie zalecanego podejścia) :
Oprócz Engine.execute()(wykonywanie bezpołączeniowe), Connection.execute()i Session.execute()możliwe jest również użycie execute()bezpośrednio w dowolnej Executablekonstrukcji. ExecutableKlasa ma własną realizację execute()- zgodnie z oficjalnej dokumentacji, jedna linia tekstu o tym, co execute()robi, jest „ skompilować i wykonać toExecutable ”. W tym przypadku musimy jawnie powiązać Executable(konstrukcję wyrażenia SQL) z Connectionobiektem lub Engineobiektem (który niejawnie pobiera Connectionobiekt), aby execute()wiedział, gdzie wykonać SQL.
Poniższy przykład dobrze to ilustruje - biorąc pod uwagę tabelę jak poniżej:
from sqlalchemy import MetaData, Table, Column, Integer
meta = MetaData()
users_table = Table('users', meta,
Column('id', Integer, primary_key=True),
Column('name', String(50)))
Jawne wykonanie czyli Connection.execute()przekazanie tekstu SQL lub skonstruowanego wyrażenia SQL do execute()metody Connection:
engine = create_engine('sqlite:///file.db')
connection = engine.connect()
result = connection.execute(users_table.select())
for row in result:
# ....
connection.close()
Jawne wykonanie bezpołączeniowe tj. Engine.execute()- przekazanie tekstu SQL lub skonstruowanego wyrażenia SQL bezpośrednio do execute()metody Engine:
engine = create_engine('sqlite:///file.db')
result = engine.execute(users_table.select())
for row in result:
# ....
result.close()
Niejawne wykonanie, tj. Executable.execute()- jest również bezpołączeniowe i wywołuje execute()metodę Executable, to znaczy wywołuje execute()metodę bezpośrednio na samej SQLkonstrukcji wyrażenia (jej instancji Executable).
engine = create_engine('sqlite:///file.db')
meta.bind = engine
result = users_table.select().execute()
for row in result:
# ....
result.close()
Uwaga: w celu wyjaśnienia podano domyślny przykład wykonania - ten sposób wykonania nie jest zdecydowanie zalecany - zgodnie z dokumentami :
„Niejawne wykonanie” to bardzo stary wzorzec użycia, który w większości przypadków jest bardziej zagmatwany niż pomocny, a jego stosowanie jest odradzane. Oba schematy wydają się zachęcać do nadużywania celowych „skrótów” w projektowaniu aplikacji, co prowadzi do późniejszych problemów.
Twoje pytania:
Jak rozumiem, jeśli ktoś używa engine.execute to tworzy połączenie, otwiera sesję (Alchemia o to dba) i wykonuje zapytanie.
Masz rację co do części "jeśli ktoś engine.executejej użyje , tworzy connection" ale nie dla "otwiera session(alchemia dba o to za ciebie) i wykonuje zapytanie" - Używanie Engine.execute()i Connection.execute()jest (prawie) tym samym, formalnie Connectionobiekt jest tworzony niejawnie , aw późniejszym przypadku jawnie tworzymy instancję. To, co naprawdę dzieje się w tym przypadku, to:
`Engine` object (instantiated via `create_engine()`) -> `Connection` object (instantiated via `engine_instance.connect()`) -> `connection.execute({*SQL expression*})`
Ale czy istnieje globalna różnica między tymi trzema sposobami wykonywania takiego zadania?
W warstwie DB jest dokładnie to samo, wszystkie wykonują SQL (wyrażenie tekstowe lub różne konstrukcje wyrażeń SQL). Z punktu widzenia aplikacji są dwie możliwości:
- Wykonanie bezpośrednie - przy użyciu
Engine.execute()lubConnection.execute()
- Korzystanie
sessions- sprawnie obsługuje transakcję jako pojedyncza jednostka-of-pracy, z łatwością za pomocą session.add(), session.rollback(), session.commit(), session.close(). Jest to sposób na interakcję z bazą danych w przypadku ORM, czyli mapowanych tabel. Zapewnia identity_map do natychmiastowego uzyskiwania dostępu do już używanych lub nowo utworzonych / dodanych obiektów podczas pojedynczego żądania.
Session.execute()ostatecznie używa Connection.execute()metody wykonania instrukcji w celu wykonania instrukcji SQL. Korzystanie z Sessionobiektu jest zalecanym sposobem SQLAlchemy ORM dla aplikacji do interakcji z bazą danych.
Fragment dokumentacji :
Należy zauważyć, że podczas korzystania z ORM SQLAlchemy te obiekty nie są generalnie dostępne; zamiast tego obiekt Session jest używany jako interfejs do bazy danych. Jednak w przypadku aplikacji, które są zbudowane wokół bezpośredniego użycia tekstowych instrukcji SQL i / lub konstrukcji wyrażeń SQL bez udziału usług zarządzania wyższego poziomu ORM, silnik i połączenie są królem (i królową?) - czytaj dalej.