Podsumowanie jednowierszowe:
Zachowanie execute()
jest taka sama we wszystkich przypadkach, ale są 3 różne sposoby, w Engine
, Connection
i Session
zajęcia.
Co to dokładnie jest execute()
:
Aby zrozumieć zachowanie execute()
, musimy przyjrzeć się Executable
klasie. Executable
jest nadklasą dla wszystkich typów obiektów typu „instrukcja”, w tym select (), delete (), update (), insert (), text () - najprościej mówiąc, Executable
jest 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-API
obiekt 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 Executable
konstrukcji. Executable
Klasa 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 Connection
obiektem lub Engine
obiektem (który niejawnie pobiera Connection
obiekt), 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 SQL
konstrukcji 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.execute
jej 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 Connection
obiekt 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 Session
obiektu 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.