對象關系教程ORM-連接
一:內連接
方法一:
for u, a in session.query(User, Address).\ filter(User.id==Address.user_id).\ filter(Address.email_address=='jack@google.com').\ all(): print(u) print(a)
方法二:
session.query(User).join(Address).\ filter(Address.email_address=='jack@google.com').\ all()
Query.join()
知道如何加入之間 User
和 Address
因為他們之間只有一個外鍵
二:左連接
query.outerjoin(User.addresses)# LEFT OUTER JOIN
三:使用別名
跨多個表查詢時,如果相同的表需要不止一次引用,表的SQL通常需要與另一個名稱別名,這樣它就可以被區分與其他表的出現。的 Query
支持這個最顯式地使用 aliased
構造。下面我們加入的 Address
實體兩次,來定位用戶在同一時間有兩個不同的電子郵件地址
>>> from sqlalchemy.orm import aliased >>> adalias1 = aliased(Address) >>> adalias2 = aliased(Address) SQL>>> for username, email1, email2 in \ ... session.query(User.name, adalias1.email_address, adalias2.email_address).\ ... join(adalias1, User.addresses).\ ... join(adalias2, User.addresses).\ ... filter(adalias1.email_address=='jack@google.com').\ ... filter(adalias2.email_address=='j25@yahoo.com'): ... print(username, email1, email2)
四:使用子查詢
Query
適用於生成報表,可以用作子查詢。假設我們想負載 User
對象數的多少 Address
每個用戶都有記錄。生成SQL的最好方法是獲取地址分組的用戶id,並加入到父。在本例中,我們使用一個左外連接,這樣我們拿回行對於那些用戶沒有任何地址
使用 Query
,我們建立一個這樣的聲明由內而外。的 statement
訪問器返回一個代表聲明由一個特定的SQL表達式 Query
——這是一個實例 select()
構造,中描述SQL表達式語言教程:
的 func
關鍵字生成SQL函數, subquery()
方法 Query
生成一個SQL表達式構造代表一個SELECT語句嵌入一個別名(實際上是縮寫query.statement.alias()
).
一旦我們有聲明,它像一個 Table
構造,如我們創建的 users
在本教程的開始。聲明可通過一個屬性的列 c
:
SELECT users.*, adr_count.address_count FROM users LEFT OUTER JOIN (SELECT user_id, count(*) AS address_count FROM addresses GROUP BY user_id) AS adr_count ON users.id=adr_count.user_id from sqlalchemy.sql import func >>> stmt = session.query(Address.user_id, func.count('*').\ ... label('address_count')).\ ... group_by(Address.user_id).subquery()
>>> from sqlalchemy.sql import func >>> stmt = session.query(Address.user_id, func.count('*').\ ... label('address_count')).\ ... group_by(Address.user_id).subquery() >>> for u, count in session.query(User, stmt.c.address_count).\ ... outerjoin(stmt, User.id==stmt.c.user_id).order_by(User.id): ... print(u, count)
五:從子查詢選擇實體
>>> stmt = session.query(Address).\ ... filter(Address.email_address != 'j25@yahoo.com').\ ... subquery() >>> adalias = aliased(Address, stmt) >>> for user, address in session.query(User, adalias).\ ... join(adalias, User.addresses): ... print(user) ... print(address)
六:使用存在
在SQL中存在關鍵字是一個布爾操作符,返回True,如果給定的表達式包含任何行。也許在很多場景中使用的連接,也用於定位行,沒有一個相關的表中相應的行。
存在一個顯式構造,它看起來像這樣:
>>> from sqlalchemy.sql import exists >>> stmt = exists().where(Address.user_id==User.id) SQL>>> for name, in session.query(User.name).filter(stmt): ... print(name)
Query
自動功能使多個運算符使用存在。以上,聲明可以表達的 User.addresses
使用的關系 any()
:
>>> for name, in session.query(User.name).\ ... filter(User.addresses.any()): ... print(name)
has()
運營商一樣嗎 any()
多對一的關系(注意 ~
運營商,這意味着“不”):
>>>session.query(Address).\ ...filter(~Address.user.has(User.name=='jack')).all()[]
七:常見的關系操作符
這是所有的運營商建立關系,每一個與它的API文檔包括使用詳情和行為:
-
__eq__()
(多對一的“=”比較):query.filter(Address.user==someuser)
-
__ne__()
(多對一的“不等於”比較):query.filter(Address.user!=someuser)
-
為空(多對一的比較,還使用嗎
__eq__()
):query.filter(Address.user==None)
-
contains()
(用於一對多收藏):query.filter(User.addresses.contains(someaddress))
-
any()
(用於收藏):query.filter(User.addresses.any(Address.email_address=='bar'))# also takes keyword arguments:query.filter(User.addresses.any(email_address='bar'))
-
has()
(用於標量引用):query.filter(Address.user.has(name='ed'))
-
Query.with_parent()
(用於任何關系):session.query(Address).with_parent(someuser,'addresses')
刪除
session.delete(jack)
session.query(User).filter_by(name='jack').count()
級聯刪除
class User(Base): ... __tablename__ = 'users' ... ... id = Column(Integer, primary_key=True) ... name = Column(String) ... fullname = Column(String) ... password = Column(String) ... ... addresses = relationship("Address", back_populates='user', ... cascade="all, delete, delete-orphan") ... ... def __repr__(self): ... return "<User(name='%s', fullname='%s', password='%s')>" % ( ... self.name, self.fullname, self.password)