SQLAlchemy ORM - praca z połączeniami
Teraz, gdy mamy dwie tabele, zobaczymy, jak tworzyć zapytania w obu tabelach w tym samym czasie. Aby skonstruować proste niejawne sprzężenie między klientem a fakturą, możemy użyć Query.filter (), aby zrównać ich powiązane kolumny. Poniżej wczytujemy jednocześnie podmioty Klient i Faktura za pomocą tej metody -
from sqlalchemy.orm import sessionmaker
Session = sessionmaker(bind = engine)
session = Session()
for c, i in session.query(Customer, Invoice).filter(Customer.id == Invoice.custid).all():
print ("ID: {} Name: {} Invoice No: {} Amount: {}".format(c.id,c.name, i.invno, i.amount))
Wyrażenie SQL emitowane przez SQLAlchemy jest następujące -
SELECT customers.id
AS customers_id, customers.name
AS customers_name, customers.address
AS customers_address, customers.email
AS customers_email, invoices.id
AS invoices_id, invoices.custid
AS invoices_custid, invoices.invno
AS invoices_invno, invoices.amount
AS invoices_amount
FROM customers, invoices
WHERE customers.id = invoices.custid
Wynik powyższych wierszy kodu jest następujący -
ID: 2 Name: Gopal Krishna Invoice No: 10 Amount: 15000
ID: 2 Name: Gopal Krishna Invoice No: 14 Amount: 3850
ID: 3 Name: Govind Pant Invoice No: 3 Amount: 10000
ID: 3 Name: Govind Pant Invoice No: 4 Amount: 5000
ID: 4 Name: Govind Kala Invoice No: 7 Amount: 12000
ID: 4 Name: Govind Kala Invoice No: 8 Amount: 8500
ID: 5 Name: Abdul Rahman Invoice No: 9 Amount: 15000
ID: 5 Name: Abdul Rahman Invoice No: 11 Amount: 6000
Rzeczywistą składnię SQL JOIN można łatwo uzyskać za pomocą metody Query.join () w następujący sposób -
session.query(Customer).join(Invoice).filter(Invoice.amount == 8500).all()
Wyrażenie SQL do łączenia zostanie wyświetlone na konsoli -
SELECT customers.id
AS customers_id, customers.name
AS customers_name, customers.address
AS customers_address, customers.email
AS customers_email
FROM customers JOIN invoices ON customers.id = invoices.custid
WHERE invoices.amount = ?
Możemy iterować wynik za pomocą pętli for -
result = session.query(Customer).join(Invoice).filter(Invoice.amount == 8500)
for row in result:
for inv in row.invoices:
print (row.id, row.name, inv.invno, inv.amount)
Z 8500 jako parametrem powiązania, wyświetlane są następujące dane wyjściowe -
4 Govind Kala 8 8500
Query.join () wie, jak łączyć te tabele, ponieważ między nimi jest tylko jeden klucz obcy. Jeśli nie było kluczy obcych lub więcej kluczy obcych, Query.join () działa lepiej, gdy używana jest jedna z następujących form -
query.join (Faktura, id == Adres.custid) | wyraźny warunek |
query.join (Customer.invoices) | określ relację od lewej do prawej |
query.join (faktura, faktury klienta) | to samo, z wyraźnym celem |
query.join ('faktury') | to samo, używając ciągu |
Podobnie, funkcja externaljoin () jest dostępna do uzyskania lewego zewnętrznego sprzężenia.
query.outerjoin(Customer.invoices)
Metoda subquery () generuje wyrażenie SQL reprezentujące instrukcję SELECT osadzoną w aliasie.
from sqlalchemy.sql import func
stmt = session.query(
Invoice.custid, func.count('*').label('invoice_count')
).group_by(Invoice.custid).subquery()
Obiekt stmt będzie zawierał instrukcję SQL, jak poniżej -
SELECT invoices.custid, count(:count_1) AS invoice_count FROM invoices GROUP BY invoices.custid
Kiedy już mamy naszą instrukcję, zachowuje się ona jak konstrukcja Table. Kolumny w instrukcji są dostępne za pośrednictwem atrybutu o nazwie c, jak pokazano w poniższym kodzie -
for u, count in session.query(Customer, stmt.c.invoice_count).outerjoin(stmt, Customer.id == stmt.c.custid).order_by(Customer.id):
print(u.name, count)
Powyższa pętla for wyświetla liczbę faktur według nazwy w następujący sposób -
Arjun Pandit None
Gopal Krishna 2
Govind Pant 2
Govind Kala 2
Abdul Rahman 2