一對多表操作
阿新 • • 發佈:2021-11-06
一對多表操作
一、建立建表
# model.py import datetime from sqlalchemy import create_engine from sqlalchemy.ext.declarative import declarative_base from sqlalchemy import Column, Integer, String, Text, ForeignKey, DateTime, UniqueConstraint, Index from sqlalchemy.orm import relationship Base = declarative_base() # make_declarative_base class Hobby(Base): __tablename__ = 'hobby' id = Column(Integer, primary_key=True) caption = Column(String(50), default='籃球') class Person(Base): __tablename__ = 'person' nid = Column(Integer, primary_key=True) name = Column(String(32), index=True, nullable=True) # hobby指的是tablename而不是類名,uselist=False hobby_id = Column(Integer, ForeignKey("hobby.id")) # 跟資料庫無關,不會新增欄位,只用於快速連結串列操作 # 類名,backref用於反向查詢 hobby = relationship('Hobby', backref='perss') def __repr__(self): return self.name def init_db(): """ 根據類建立資料庫表 :return: """ engine = create_engine( "mysql+pymysql://root:[email protected]:3306/db_flask?charset=utf8", max_overflow=0, # 超過連線池大小外最多建立的連線 pool_size=5, # 連線池大小 pool_timeout=30, # 池中沒有執行緒最多等待的時間,否則報錯 pool_recycle=-1 # 多久之後對執行緒池中的執行緒進行一次連線的回收(重置) ) Base.metadata.create_all(engine) def drop_db(): """ 根據類刪除資料庫表 :return: """ engine = create_engine( "mysql+pymysql://root:[email protected]:3306/db_flask?charset=utf8", max_overflow=0, # 超過連線池大小外最多建立的連線 pool_size=5, # 連線池大小 pool_timeout=30, # 池中沒有執行緒最多等待的時間,否則報錯 pool_recycle=-1 # 多久之後對執行緒池中的執行緒進行一次連線的回收(重置) ) Base.metadata.drop_all(engine) if __name__ == '__main__': # 建立表 init_db() # 刪除表 # drop_db()
二、新增資料
from sqlalchemy.orm import sessionmaker from sqlalchemy import create_engine from model import Users, Hobby, Person engine = create_engine("mysql+pymysql://root:[email protected]:3306/db_flask", max_overflow=0, pool_size=5) Session = sessionmaker(bind=engine) session = Session() # 1. 新增資料 # 方式一 session.add_all([ Hobby(caption='乒乓球'), Hobby(caption='羽毛球'), Person(name='張三', hobby_id=1), Person(name='李四', hobby_id=2), ]) # 方式二 # Hobby 愛好會自動插入一個愛好,即使存在也會插入資料 # 正向查詢欄位hoppy新增 person = Person(name='張三', hobby=Hobby(caption='跑腿')) session.add(person) # 方式三 hb = Hobby(caption='羽毛球') # 通過反向查詢欄位,新增資料perss 是關聯欄位 hb.perss = [Person(name='文飛'), Person(name='波波')] session.add(hb) session.commit()
三、正、反向查詢
3.1 正向查詢
from sqlalchemy.orm import sessionmaker from sqlalchemy import create_engine from model import Users, Hobby, Person engine = create_engine("mysql+pymysql://root:[email protected]:3306/db_flask", max_overflow=0, pool_size=5) Session = sessionmaker(bind=engine) session = Session() # 2. relationship正向查詢 person = session.query(Person).first() print(person.name) # 正向查詢, 當前類中有外來鍵成為正向查詢,正向查詢只會有一個與其對應的愛好(單條記錄) print(person.hobby) print(person.hobby.caption)
3.1 反向查詢
from sqlalchemy.orm import sessionmaker
from sqlalchemy import create_engine
from model import Users, Hobby, Person
engine = create_engine("mysql+pymysql://root:[email protected]:3306/db_flask", max_overflow=0, pool_size=5)
Session = sessionmaker(bind=engine)
session = Session()
# 3. relationship 反向查詢
hobby = session.query(Hobby).filter(Hobby.id == 1).first()
print(hobby.caption)
# 物件列表,反向查詢的結果是一個類表物件(因為是一對多的關係,在person可能有多個愛好被被關聯),所以要使用循壞一個個遍歷
print(hobby.perss)
print(hobby.perss[0].nid, hobby.perss[0].name)
3.3 斷關聯連表查詢
from sqlalchemy.orm import sessionmaker
from sqlalchemy import create_engine
from model import Users, Hobby, Person
engine = create_engine("mysql+pymysql://root:[email protected]:3306/db_flask", max_overflow=0, pool_size=5)
Session = sessionmaker(bind=engine)
session = Session()
# 3. 斷關聯
# 斷關聯:是兩張表中沒有設定外來鍵關聯,所以只能通過邏輯進行關聯,使用.join( Person.hobby_id == Hobby.id)
# Person.hobby_id == Hobby.id 斷關聯這個條件必須要寫,通過join實現表之間的關聯
# isouter=True 左關聯,False為 inner join 等值關聯
# query中的表和join表來調換表的查詢關係
ret = session.query(Person).join(Hobby, Person.hobby_id == Hobby.id, isouter=False)
print(ret)
# 設定了外來鍵關聯,就不需要設定 Person.hobby_id == Hobby.id 條件
person_list = session.query(Hobby).join(Person, isouter=True)
print(person_list)
person_list = session.query(Person, Hobby).join(Hobby).all()
print(person_list)
for row in person_list:
# print(row.name,row.caption)
# 第一個為person物件, 第二位hobby物件
print(row[0].name, row[1].caption)
3.4 通過relationship連表查詢
from sqlalchemy.orm import sessionmaker
from sqlalchemy import create_engine
from model import Users, Hobby, Person
engine = create_engine("mysql+pymysql://root:[email protected]:3306/db_flask", max_overflow=0, pool_size=5)
Session = sessionmaker(bind=engine)
session = Session()
# 通過relationship
person_list = session.query(Person).all()
print(person_list)
for row in person_list:
print(row.name, row.hobby.caption)
# obj = session.query(Hobby).filter(Hobby.id == 1).first()
# persons = obj.perss
# print(persons)
三、總結
- 新增資料:可以通過add_all新增資料並設定關聯外來鍵欄位值,還可以通過正反向查詢向新增表之間的關係,會自定設定關聯的外來鍵值
- 正向查詢:當前表中有外來鍵欄位稱為正向查詢,正向查詢單條資料對一個愛好資料
- 反向查詢:當前表中沒有外來鍵欄位稱為反向查詢,反向查詢單條資料可會被多個人喜歡,所以查出來為列表物件,是一個集合
- 連表查詢:可以通過兩種方式進行查詢,一種是通過表之間的關鍵關係通過 .join方法實現連表查詢,需要注意的是表之間是否有級聯關係,也就是是否設定了外來鍵,如果沒有則需要在.join中通過邏輯條件實現連表查詢,通過調至query和.join中類名實現左右連線查詢,第二種方式就是通過正反向查詢實現連表查詢