Python之路第十三天,高級(7)-詳述數據庫一對多,多對多表關系的設計以及如何查詢


一對多表設計和查詢方法

#!/usr/bin/env python3
# Author: Zhangxunan

from sqlalchemy import create_engine
from sqlalchemy.ext.declarative import declarative_base
from sqlalchemy import Column, Integer, String, ForeignKey, UniqueConstraint, Index, Table
from sqlalchemy.orm import sessionmaker, relationship

# 連接數據庫
engine = create_engine("mysql+pymysql://root:123456@127.0.0.1:3306/test", max_overflow=5)

# 創建基類,所有創建表的類都要繼承這個基類
Base = declarative_base()

# 創建會話,通過會話去操作數據庫
Session = sessionmaker(bind=engine)
session = Session()


# 一對多關系(一個組可以有很多人,一個人只能屬於一個組)
class Group(Base):
    __tablename__ = 'groups'
    nid = Column(Integer, primary_key=True,autoincrement=True)
    caption = Column(String(32))


class User(Base):
    __tablename__ = 'users'
    nid = Column(Integer, primary_key=True,autoincrement=True)
    username = Column(String(32))
    group_id = Column(Integer, ForeignKey('groups.nid'))
    group = relationship("Group", backref='user')


def init_db():
    """
    通過上面的類創建表
    :return: None
    """
    Base.metadata.create_all(engine)


def drop_db():
    """
    刪除表
    :return: None
    """
    Base.metadata.drop_all(engine)


# 插入數據
# session.add_all([
#     Group(caption='SA'),
#     Group(caption='DEV'),
#     Group(caption='TEST'),
#     Group(caption='DBA')
# ])
# session.commit()

# session.add_all([
#     User(username='tom', group_id=1),
#     User(username='jerry', group_id=1),
#     User(username='jack', group_id=2),
#     User(username='rose', group_id=3),
#     User(username='eric', group_id=4),
#     User(username='james', group_id=4)
# ])
#
# session.commit()


# 輸出原生sql
sql = session.query(User.username, Group.caption).join(Group, isouter=True).filter(User.username == 'jack')
print(sql)

# 查詢jack屬於哪個組
ret = session.query(User.username, Group.caption).join(Group, isouter=True).filter(User.username == 'jack').first()
print(ret)

# 輸出原生sql
sql = session.query(User.username, Group.caption).join(Group, isouter=True)
print(sql)

# 查詢所有用戶分別屬於哪個組
ret = session.query(User.username, Group.caption).join(Group, isouter=True).all()
print(ret)

# 輸出原生sql
sql = session.query(User.username, Group.caption).join(Group, isouter=True).filter(Group.caption == 'SA')
print(sql)

# 查詢SA組有哪些人
ret = session.query(User.username, Group.caption).join(Group, isouter=True).filter(Group.caption == 'SA').all()
print(ret)

# 正向查詢 (group = relationship("Group", backref='user'),通過這一句建立關系,然后可以通過這種關系查詢更方便)
# 查詢jack用戶屬於哪個組
ret = session.query(User).filter(User.username == 'jack').first()
print(ret.username, ret.group.caption)

# 查詢所有用戶分別屬於哪個組
ret = session.query(User).all()
for obj in ret:
    # obj代指user表的每一行數據
    # obj.group代指group對象,
    print(obj.nid, obj.username, obj.group.caption)

# 反向查詢
# 查詢SA組有哪些人
obj = session.query(Group).filter(Group.caption == 'SA').first()
# obj 指代groups表里組名為SA的那一行數據
# obj.user 指代users對象(組為SA的用戶數據)
for item in obj.user:
    print(item.username, end=' ')

多對多的表設計和查詢方法

#!/usr/bin/env python3
# Author: Zhangxunan
from sqlalchemy import create_engine
from sqlalchemy.ext.declarative import declarative_base
from sqlalchemy import Column, Integer, String, ForeignKey, UniqueConstraint, Index, Table
from sqlalchemy.orm import sessionmaker, relationship

# 連接數據庫
engine = create_engine("mysql+pymysql://root:123456@127.0.0.1:3306/test", max_overflow=5)

# 創建基類,所有創建表的類都要繼承這個基類
Base = declarative_base()

# 創建會話,通過會話去操作數據庫
Session = sessionmaker(bind=engine)
session = Session()


# 多對多(需要第三張表,專門用來存關系,一個用戶可以登錄多個服務器,一個服務器上可以有多個用戶)
class HostToHostUser(Base):
    __tablename__ = 'host_to_host_user'
    nid = Column(Integer, primary_key=True, autoincrement=True)
    host_id = Column(Integer, ForeignKey('host.nid'))
    host_user_id = Column(Integer, ForeignKey('host_user.nid'))


class Host(Base):
    __tablename__ = 'host'
    nid = Column(Integer, primary_key=True, autoincrement=True)
    hostname = Column(String(32))
    port = Column(String(32))
    ip = Column(String(32))

    host_user = relationship('HostUser', secondary=lambda: HostToHostUser.__table__, backref='host')


class HostUser(Base):
    __tablename__ = 'host_user'
    nid = Column(Integer, primary_key=True,autoincrement=True)
    username = Column(String(32))


def init_db():
    """
    通過上面的類創建表
    :return: None
    """
    Base.metadata.create_all(engine)


def drop_db():
    """
    刪除表
    :return: None
    """
    Base.metadata.drop_all(engine)

# session.add_all([
#     Host(hostname='web1', port='22', ip='192.168.1.65'),
#     Host(hostname='web2', port='22', ip='192.168.1.66'),
#     Host(hostname='web3', port='22', ip='192.168.1.67'),
#     Host(hostname='web4', port='22', ip='192.168.1.68'),
#     Host(hostname='web5', port='22', ip='192.168.1.69'),
# ])
# session.commit()


# session.add_all([
#     HostUser(username='root'),
#     HostUser(username='tom'),
#     HostUser(username='jerry'),
#     HostUser(username='jack'),
#     HostUser(username='rose'),
# ])
# session.commit()

# session.add_all([
#     HostToHostUser(host_id=1, host_user_id=1),
#     HostToHostUser(host_id=1, host_user_id=2),
#     HostToHostUser(host_id=1, host_user_id=3),
#     HostToHostUser(host_id=2, host_user_id=2),
#     HostToHostUser(host_id=2, host_user_id=4),
#     HostToHostUser(host_id=2, host_user_id=3),
# ])
# session.commit()

# 需求:獲取web1服務器中的所有用戶
# 原始方式需要經過三步:
# 第一步:查詢web1的服務器ID
host_obj = session.query(Host).filter(Host.hostname == 'web1').first()
print(host_obj.nid)

# 第二步:查詢第三張表(關系表)查詢所有用戶的ID  host_id == host_obj.nid
host_2_host_user = session.query(HostToHostUser.host_user_id).filter(HostToHostUser.host_id == host_obj.nid).all()
uids = list(zip(*host_2_host_user))[0]
print(uids)

# 第三步:根據用戶ID查找所有用戶
users = session.query(HostUser.username).filter(HostUser.nid.in_(uids)).all()
users = [x[0] for x in users]
print(users)

# 當然也可以把上面三步合成一個sql,但太長了

# 正向查詢
# host_user = relationship('HostUser', secondary=lambda: HostToHostUser.__table__, backref='host')
# 上面這個話的意思是說給通過第三張表HostToHostUser給HostUser表建立關系
# host_obj是一個對象,是表示hostname=='web1'的那一行數據 host_obj.nid為web1的nid
host_obj = session.query(Host).filter(Host.hostname == 'web1').first()
for item in host_obj.host_user:
    print(item.username, end=' ')


# 需求2:獲取tom用戶可以登錄哪些服務器
# 原始方式需要經過三步
# 第一步:查詢tom用戶的id
user_obj = session.query(HostUser).filter(HostUser.username == 'tom').first()
print(user_obj.nid)

# 第二步:查詢第三張表(關系表),查詢所有服務器的ID, 條件是 user_obj.nid == host_user_id
host_ids = session.query(HostToHostUser.host_id).filter(HostToHostUser.host_user_id == user_obj.nid).all()
host_ids = list(zip(*host_ids))[0]
print(host_ids)

# 第三步: 根據服務器ID查找服務器hostname
hosts = session.query(Host).filter(Host.nid.in_(host_ids)).all()
hosts = [x.hostname for x in hosts]
print(hosts)

# 反向查詢
# host_user = relationship('HostUser', secondary=lambda: HostToHostUser.__table__, backref='host')
# 上面這個話的意思是說給通過第三張表HostToHostUser給HostUser表建立關系
host_user_obj = session.query(HostUser).filter(HostUser.username == 'tom').first()
for item in host_user_obj.host:
    print(item.hostname, end=' ')
print()


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM