python -- sqlalchemy

一、sqlAlchemy簡介python

#!/usr/bin/env python
# -*- coding:utf8 -*-

'''
sqlalchemy是orm(對象關係映射),是第三方庫,須要安裝。
orm優勢:
    隱藏了數據訪問細節,「封閉」的通用數據庫交互,ORM的核心。他使得咱們的通用數據庫交互變得簡單易行,而且徹底不用考慮該死的SQL語句。快速開發,由此而來。
    ORM使咱們構造固化數據結構變得簡單易行。

orm缺點:
    無可避免的,自動化意味着映射和關聯管理,代價是犧牲性能(早期,這是全部不喜歡ORM人的共同點)。如今的各類ORM框架都在嘗試使用各類方法來減輕這塊(LazyLoad,Cache),
效果仍是很顯著的。 Dialect(方言)用於和數據API進行交流,根據配置文件的不一樣調用不一樣的數據庫API,從而實現對數據庫的操做: MySQL-Python mysql+mysqldb://<user>:<password>@<host>[:<port>]/<dbname> pymysql mysql+pymysql://<username>:<password>@<host>/<dbname>[?<options>] MySQL-Connector mysql+mysqlconnector://<user>:<password>@<host>[:<port>]/<dbname> cx_Oracle oracle+cx_oracle://user:pass@host:port/dbname[?key=value&key=value...]
'''

二、sqlAlchemy鏈接mysql基礎mysql

#!/usr/bin/env python
# -*- coding:utf8 -*-

import sqlalchemy
from sqlalchemy import create_engine
from sqlalchemy.ext.declarative import declarative_base
from sqlalchemy import Column, Integer, String
from sqlalchemy.orm import sessionmaker

engine = create_engine("mysql+pymysql://root:root@127.0.0.1:3306/pystudy?charset=utf8",echo=True)
        #端口默承認不寫,echo=True返回建立過程執行細節
# engine = create_engine("mysql+pymysql://root:root@127.0.0.1:3306/pystudy",encoding='utf8')

Base = declarative_base()  #生成orm基類

class Host(Base):  #映射,把表映射成一個類
    __tablename__ = 'hosts'   #表名
    id = Column(Integer, primary_key=True, autoincrement=True)
                    #autoincrement=True  默認就是True,能夠不寫,自增
    hostname = Column(String(64), unique=True, nullable=False)
    ip_addr = Column(String(128), unique=True, nullable=False)
    port = Column(Integer, default=22)

Base.metadata.create_all(engine) #建立全部表結構(若是該表已經存在,do nothing)

if __name__ == '__main__':
    #上面的代碼只是建立一個表,若要對指定表進行增刪查改等操做,要先創建一個會話
    Session_class = sessionmaker(bind=engine) #建立與數據庫的會話session_class類
        #注意:這裏返回給session的是個class,不是實例
    Session = Session_class()  #生成session實例,接下來就能夠進行操做了

#添加數據
    # h1 = Host(hostname='localhost', ip_addr='127.0.0.1')
    # h2 = Host(hostname='txowner',ip_addr='127.0.0.1', port=9999)
    # # session.add(h1)  #一次把一條數據對象添加到會話中,還沒插入
    # # session.add(h2)
    # Session.add_all([h1,h2])  #同時把多條數據對象添加到會話中,等待插入(參數以列表形式傳遞)
    # Session.commit()  #此時纔將數據插入到表中(這樣更好的支持回滾操做)

#修改數據(先查詢出來再修改,不能直接修改)
    # res = Session.query(Host).filter(Host.hostname == 'txowner').all()
    # # print("=====>",res)  # first表示第一個  all 表示所有
    # res.hostname = 'test server'
    # Session.commit()  #這裏不強求,一般加上

#刪除數據(先查詢出來再刪除,不能直接刪除)
    res = Session.query(Host).filter(Host.hostname == 'test server').first()
    # print("--->",res)
    Session.delete(res)  #一次只刪除一條
    Session.commit()

#查詢數據
'''
在sqlalchemy中,不少sql關鍵字爲了與python的關鍵字區分,作了以下改變:
    函數 in_ : 接收列表參數,做用與sql內置的in同樣 
             eg:user.username.in_(['root','admin']) 
       not in:  eg:  ~user.username.in_(['root','admin'])
    is None :  eg: user.username.is_(None)、user.username == None
    is not None eg: user.username.isnot(None)
    
    like :  user.userneme.like('ad%')
    
    and_、or_ 在sqlalchemy中,須要單獨導入, 跟的幾個參數就是幾個條件
    
    filter、filter_by 區別:
        filter在判斷條件時,等號要用 '=='
        filter_by在判斷條件時,等號用 '='
    order_by 按什麼來排序 eg: order_by(user.id) 
'''

三、鏈接查詢sql

#!/usr/bin/env python
# -*- coding:utf8 -*-

'''
鏈接查詢:
    把幾張表根據鏈接方式鏈接到一塊兒,返回一個多個表組成的射影
    
原生sql語句:  eg: 表a -> 列 ca    表b -> 列 cb 
內鏈接查詢(求兩表的交集組成的表):select * from a inner join b on a.ca = b.cb
左鏈接查詢(表a的全列出來,表b沒有這麼多就填null,以a爲準):select * from a left join b on a.ca = b.cb
右鏈接查詢(表b的全列出來,表a沒有這麼多就填null,以b爲準):select * from a right join b on a.ca = b.cb

涉及到多張表的查詢就要用join鏈接查詢
'''
import sqlalchemy
from sqlalchemy import Column, Integer, String, ForeignKey,func
from sqlalchemy import create_engine
from sqlalchemy.ext.declarative import declarative_base
from sqlalchemy.orm import sessionmaker, relationship

#鏈接數據庫
engine = create_engine("mysql+pymysql://root:root@localhost:3306/pystudy?charset=utf8",echo=True)

#生成orm基類
Base = declarative_base()

#這裏的應用情景是一個主機只屬於一個組,一個組能夠有多個主機
class Host(Base):
    __tablename__ = 'hosts'
    id = Column(Integer, primary_key=True)
    hostname = Column(String(64),unique=True,nullable=False)
    ip_addr = Column(String(128),unique=True,nullable=False)
    port = Column(Integer, default=22)
    group_id = Column(Integer,ForeignKey('group.id'))
    group_map = relationship('Group', backref='host_map')   #這裏相似於反射,把Group表對象反射到當前屬性

class Group(Base):
    __tablename__ = 'group'
    id = Column(Integer,primary_key=True)
    name = Column(String(64),unique=True,nullable=False)


#建立全部表結構(若是該表已經存在,do nothing)
Base.metadata.create_all(engine)

if __name__ == '__main__':
    #生成session實例
    Session_class = sessionmaker(bind=engine)  #生成session_class類
    session = Session_class()  #實現session_class類的實例

    #在這裏表中以前就有插入的數據

    #經過host表查詢group的信息(relationship的做用)
    h = session.query(Host).filter(Host.hostname=='localhost').first()
    print('--->',h.group_map.name)

    # 經過group表查詢hosts的信息(relationship的做用)
    g = session.query(Group).filter(Group.id == 2).first()
    print('--->', g.host_map)

    #鏈接查詢(內鏈接查詢)
    join_select_all1 = session.query(Host).join(Host.group_map)
    print("join_select_all:",join_select_all1)  #這裏結果是返回的sql原生語句
    '''
    join_select_all: SELECT hosts.id AS hosts_id, hosts.hostname AS hosts_hostname, hosts.ip_addr AS hosts_ip_addr, hosts.port AS hosts_port,
hosts.group_id AS hosts_group_id FROM hosts INNER JOIN `group` ON `group`.id = hosts.group_id
''' join_select_all2 = session.query(Host).join(Host.group_map).all() print("join_select_all:", join_select_all2) #這裏返回的查詢結果 ''' join_select_all: [<__main__.Host object at 0x000001500637D080>, <__main__.Host object at 0x000001500637D358>] ''' #在sqlalchemy中,聚合函數(count、sum、max...)在func中,要導入 #group_by 分組聚合(group_by加在條件判斷(filter)後面) join_select_all3 = session.query(Host,func.count(Group.name)).join(Host.group_map).group_by(Group.id).all() print("分組聚合後的結果:",join_select_all3) session.commit()

四、一對多外鍵關聯數據庫

#!/usr/bin/env python
# -*- coding:utf8 -*-

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

#鏈接數據庫
engine = create_engine("mysql+pymysql://root:root@localhost:3306/pystudy?charset=utf8",echo=True)

#生成orm基類
Base = declarative_base()

#這裏的應用情景是一個主機只屬於一個組,一個組能夠有多個主機
class Host(Base):
    __tablename__ = 'host'
    id = Column(Integer, primary_key=True)
    hostname = Column(String(64),unique=True,nullable=False)
    ip_addr = Column(String(128),unique=True,nullable=False)
    port = Column(Integer, default=22)
    group_id = Column(Integer,ForeignKey('group.id'))
    group_map = relationship('Group')   #這裏相似於反射,把Group表對象反射到當前屬性

class Group(Base):
    __tablename__ = 'group'
    id = Column(Integer,primary_key=True)
    name = Column(String(64),unique=True,nullable=False)


#建立全部表結構(若是該表已經存在,do nothing)
Base.metadata.create_all(engine)

if __name__ == '__main__':
    #生成session實例
    Session_class = sessionmaker(bind=engine)  #生成session_class類
    session = Session_class()  #實現session_class類的實例
    '''
         #插入數據
        g1 = Group(name='g1')   #在group表中插入三條數據,建立三個組
        g2 = Group(name='g2')
        g3 = Group(name='g3')
        session.add_all([g1,g2,g3])  #這裏只是把對象添加到會話,尚未插入

        # session.commit()

        h1 = Host(hostname='localhost', ip_addr='127.0.0.1', port=9999, group_id=g2.id)
        h2 = Host(hostname='ubuntu', ip_addr='192.168.22.132', port=6666, group_id=g1.id)
        session.add_all([h1,h2])

        session.commit()

    '''
    '''
        #兩表連接修改數據
        g1 = session.query(Group).filter(Group.name == 'g1').first()
        g2 = session.query(Group).filter(Group.name == 'g2').first()
        h1 = session.query(Host).filter(Host.hostname == 'localhost').update({'group_id':g2.id})
        h2 = session.query(Host).filter(Host.hostname == 'ubuntu').update({'group_id': g1.id})
        session.commit()
    '''
    #經過host表查詢group的信息(relationship的做用)
    h = session.query(Host).filter(Host.hostname=='localhost').first()
    print('--->',h.group_map.name)
    session.commit()

五、一對多外鍵關聯改進ubuntu

#!/usr/bin/env python
# -*- coding:utf8 -*-

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

#鏈接數據庫
engine = create_engine("mysql+pymysql://root:root@localhost:3306/pystudy?charset=utf8",echo=True)

#生成orm基類
Base = declarative_base()

#這裏的應用情景是一個主機屬於一個組,一個組能夠有多個主機
class Host(Base):
    __tablename__ = 'host'
    id = Column(Integer, primary_key=True)
    hostname = Column(String(64),unique=True,nullable=False)
    ip_addr = Column(String(128),unique=True,nullable=False)
    port = Column(Integer, default=22)
    group_id = Column(Integer,ForeignKey('group.id'))
    group_map = relationship('Group',backref='host_list')
        #這裏相似於反射,把Group表對象反射到當前屬性
    # group_map = relationship('Group',back_populates='host_list')
    # back_populates做用與backref同樣,可是backref只須要一個表指明,
    # 而back_populates要兩個表同時有,
    # 兩個表直接不寫back_populates同樣能夠實現,因此通常用backref

class Group(Base):
    __tablename__ = 'group'
    id = Column(Integer,primary_key=True)
    name = Column(String(64),unique=True,nullable=False)
    # host_list = relationship('Host',back_populates='group_map')


#建立全部表結構(若是該表已經存在,do nothing)
Base.metadata.create_all(engine)

if __name__ == '__main__':
    #生成session實例
    Session_class = sessionmaker(bind=engine)  #生成session_class類
    session = Session_class()  #實現session_class類的實例
    '''
         #插入數據
        g1 = Group(name='g1')   #在group表中插入三條數據,建立三個組
        g2 = Group(name='g2')
        g3 = Group(name='g3')
        session.add_all([g1,g2,g3])  #這裏只是把對象添加到會話,尚未插入

        # session.commit()

        h1 = Host(hostname='localhost', ip_addr='127.0.0.1', port=9999, group_id=g2.id)
        h2 = Host(hostname='ubuntu', ip_addr='192.168.22.132', port=6666, group_id=g1.id)
        session.add_all([h1,h2])

        session.commit()

    '''
    '''
        #兩表連接修改數據
        g1 = session.query(Group).filter(Group.name == 'g1').first()
        g2 = session.query(Group).filter(Group.name == 'g2').first()
        h1 = session.query(Host).filter(Host.hostname == 'localhost').update({'group_id':g2.id})
        h2 = session.query(Host).filter(Host.hostname == 'ubuntu').update({'group_id': g1.id})
        session.commit()
    '''
    #經過host表查詢group的信息(relationship的做用)
    h = session.query(Host).filter(Host.hostname=='localhost').first()
    g = session.query(Group).filter(Group.id == 2).first()
    print('g:',g.name,g.id)
    print('--->',h.group_map.name)
    print('===>',g.host_list)
    # g.host_list.group_id 報錯,這裏到底查詢出來的是什麼?
    session.commit()

六、多對多外鍵關聯centos

#!/usr/bin/env python
# -*- coding:utf8 -*-

'''
多對多外鍵關聯時跟不一樣程序進程間通訊同樣,須要第三方中介
在這裏兩個表多對多關聯查詢時,經常須要第三個表只做爲中間橋樑

多對多關聯:
    一、建立中間表,關聯其餘兩個表,不用class方式,直接是相似這種方式:
        Host2Group = Table('host_2_group',Base.metadata,
            Column('host_id',ForeignKey('host.id'),primary_key=True),
            Column('group.id',ForeignKey('group.id'),primary_key=True),
        )
        Host2Group是一個實例,再也不是類
    
    二、建立兩個表映射類,並在兩個類中分別指定中間表實例
        class Host(Base):
            __tablename__ = 'host'
            id = Column(Integer, primary_key=True)
            hostname = Column(String(64),unique=True,nullable=False)
            ip_addr = Column(String(128),unique=True,nullable=False)
            port = Column(Integer, default=22)
            groups = relationship('Group',
                                secondary=Host2Group, #指定中間表實例
                                backref=hosts   #設置反向的反射
                                )
        
    三、先建立組數據,在建立主機數據,(沒有區分前後同樣可行)而後將他們關聯
       
'''

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

#鏈接數據庫
engine = create_engine("mysql+pymysql://root:root@localhost:3306/pystudy?charset=utf8",
                       echo=True)

#生成orm基類
Base = declarative_base()

#建立一箇中間表的實例
Host2Group = Table('host_2_group',Base.metadata,
                   Column('host.id',ForeignKey('host.id'), primary_key=True),
                   Column('group.id',ForeignKey('group.id'), primary_key=True),
                   #這裏把兩個列都設置爲主鍵,使得每一條數據中這兩個列都爲惟一肯定
                   )

#這裏的應用情景是一個主機屬於多個組,一個組能夠有多個主機
class Host(Base):
    __tablename__ = 'host'
    id = Column(Integer, primary_key=True)
    hostname = Column(String(64), unique=True, nullable=False)
    ip_addr = Column(String(128), unique=True, nullable=False)
    port = Column(Integer, default=22)
    # group_id = Column(Integer,ForeignKey('group.id'))
    # #這裏就不用再設置外鍵,secondary替代工做
    groups = relationship('Group',
                             secondary=Host2Group,
                             backref='hosts')
        #這裏相似於反射,把Group表對象反射到當前屬性
    # group_map = relationship('Group',back_populates='host_list')
    # back_populates做用與backref同樣,可是backref只須要一個表指明,
    # 而back_populates要兩個表同時有,
    # 兩個表直接不寫back_populates同樣能夠實現,因此通常用backref

    #打印字符串格式
    def __repr__(self):
        return "<id=%s, hostname=%s, ip_addr=%s, port=%s>" %(self.id,
                                                             self.hostname,
                                                             self.ip_addr,
                                                             self.port)

class Group(Base):
    __tablename__ = 'group'
    id = Column(Integer, primary_key=True)
    name = Column(String(64), unique=True, nullable=False)
    # host_list = relationship('Host',back_populates='group_map')

    def __repr__(self):
        return "<id=%s, name=%s>" %(self.id, self.name)

#建立全部表結構(若是該表已經存在,do nothing)
Base.metadata.create_all(engine)

if __name__ == '__main__':
    #生成session實例
    Session_class = sessionmaker(bind=engine)  #生成session_class類
    session = Session_class()  #實現session_class類的實例

    '''
    #插入數據(插入數據只能插入一次,若數據存在後再進行插入就會報錯)
    #實例化Host類的對象(host表中的一條條數據)
    h1 = Host(hostname='localhost', ip_addr='127.0.0.1', port=6666)
    h2 = Host(hostname='ubuntu', ip_addr='192.168.22.132', port=9999)
    h3 = Host(hostname='centos', ip_addr='192.168.22.129')
    #把對象添加到會話中
    session.add_all([h1, h2, h3])

    #實例化Group類的對象(group表中的一條條數據)
    g1 = Group(name='g1')
    g2 = Group(name='g2')
    g3 = Group(name='g3')
    g4 = Group(name='g4')
    session.add_all([g1, g2, g3, g4])

    #把實例化的對象數據分別插入到對應表中
    session.commit()
    '''

    #關聯數據
    #分別查找出主機和要設置的所屬組,再對他們進行關聯
    g = session.query(Group).all()
    g4 = session.query(Group).filter(Group.name=='g4').first()
    h1 = session.query(Host).filter(Host.hostname=='localhost').first()

    h1.groups = g  #對一個主機設置全部分組 h1.groups就是一個列表
    h1.groups.pop()   #刪除某個主機的指定分組
    h1.groups = [g4]  #這裏必須是列表
    session.commit()

    print('g:',g)
    #[<id=1, name=g1>, <id=2, name=g2>, <id=3, name=g3>, <id=4, name=g4>]
    #type g: <class 'list'>
    print('g4:',g4)
    print('h1:',h1)
    #<id=1, hostname=localhost, ip_addr=127.0.0.1, port=6666>
    print('反向測試:',g4.hosts)
    #反向測試: [<id=1, hostname=localhost, ip_addr=127.0.0.1, port=6666>]
相關文章
相關標籤/搜索