SqlAlchemy
SQLAlchemy是Python编程语言下的一款ORM框架,该框架建立在数据库API之上,使用关系对象映射进行数据库操作,简言之便是:将对象转换成SQL,然后使用数据API执行SQL并获取执行结果。
Dialect用于和数据API进行交流,根据配置文件的不同调用不同的数据库API,从而实现对数据库的操作,如:
1 MySQL-Python 2 mysql+mysqldb://<user>:<password>@<host>[:<port>]/<dbname> 3 4 pymysql 5 mysql+pymysql://<username>:<password>@<host>/<dbname>[?<options>] 6 7 MySQL-Connector 8 mysql+mysqlconnector://<user>:<password>@<host>[:<port>]/<dbname> 9 10 cx_Oracle 11 oracle+cx_oracle://user:pass@host:port/dbname[?key=value&key=value...] 12 13 更多详见:http://docs.sqlalchemy.org/en/latest/dialects/index.html
步骤一:
使用 Engine/ConnectionPooling/Dialect 进行数据库操作,Engine使用ConnectionPooling连接数据库,然后再通过Dialect执行SQL语句。
1 from sqlalchemy import create_engine 2 3 4 engine = create_engine("mysql+mysqldb://root:123@127.0.0.1:3306/s11", max_overflow=5) 5 6 engine.execute( 7 "INSERT INTO ts_test (a, b) VALUES ('2', 'v1')" 8 ) 9 10 engine.execute( 11 "INSERT INTO ts_test (a, b) VALUES (%s, %s)", 12 ((555, "v1"),(666, "v1"),) 13 ) 14 engine.execute( 15 "INSERT INTO ts_test (a, b) VALUES (%(id)s, %(name)s)", 16 id=999, name="v1" 17 ) 18 19 result = engine.execute('select * from ts_test') 20 result.fetchall()
步骤二:
使用 Schema Type/SQL Expression Language/Engine/ConnectionPooling/Dialect 进行数据库操作。Engine使用Schema Type创建一个特定的结构对象,之后通过SQL Expression Language将该对象转换成SQL语句,然后通过 ConnectionPooling 连接数据库,再然后通过 Dialect 执行SQL,并获取结果。
1 from sqlalchemy import create_engine, Table, Column, Integer, String, MetaData, ForeignKey 2 3 metadata = MetaData() 4 5 user = Table('user', metadata, 6 Column('id', Integer, primary_key=True), 7 Column('name', String(20)), 8 ) 9 10 color = Table('color', metadata, 11 Column('id', Integer, primary_key=True), 12 Column('name', String(20)), 13 ) 14 engine = create_engine("mysql+mysqldb://root@localhost:3306/test", max_overflow=5) 15 16 metadata.create_all(engine)
增删改查
1 from sqlalchemy import create_engine, Table, Column, Integer, String, MetaData, ForeignKey 2 3 metadata = MetaData() 4 5 user = Table('user', metadata, 6 Column('id', Integer, primary_key=True), 7 Column('name', String(20)), 8 ) 9 10 color = Table('color', metadata, 11 Column('id', Integer, primary_key=True), 12 Column('name', String(20)), 13 ) 14 engine = create_engine("mysql+mysqldb://root:123@127.0.0.1:3306/s11", max_overflow=5) 15 16 conn = engine.connect() 17 18 # 创建SQL语句,INSERT INTO "user" (id, name) VALUES (:id, :name) 19 conn.execute(user.insert(),{'id':7,'name':'seven'}) 20 conn.close() 21 22 # sql = user.insert().values(id=123, name='wu') 23 # conn.execute(sql) 24 # conn.close() 25 26 # sql = user.delete().where(user.c.id > 1) 27 28 # sql = user.update().values(fullname=user.c.name) 29 # sql = user.update().where(user.c.name == 'jack').values(name='ed') 30 31 # sql = select([user, ]) 32 # sql = select([user.c.id, ]) 33 # sql = select([user.c.name, color.c.name]).where(user.c.id==color.c.id) 34 # sql = select([user.c.name]).order_by(user.c.name) 35 # sql = select([user]).group_by(user.c.name) 36 37 # result = conn.execute(sql) 38 # print result.fetchall() 39 # conn.close()
1 from sqlalchemy import create_engine 2 from sqlalchemy.ext.declarative import declarative_base 3 from sqlalchemy import Column, Integer, String 4 from sqlalchemy.orm import sessionmaker 5 6 Base = declarative_base() #生成一个SqlORM 基类 7 8 9 engine = create_engine("mysql+mysqldb://root@localhost:3306/test",echo=False) 10 11 12 class Host(Base): 13 __tablename__ = 'hosts' 14 id = Column(Integer,primary_key=True,autoincrement=True) 15 hostname = Column(String(64),unique=True,nullable=False) 16 ip_addr = Column(String(128),unique=True,nullable=False) 17 port = Column(Integer,default=22) 18 19 Base.metadata.create_all(engine) #创建所有表结构 20 21 if __name__ == '__main__': 22 SessionCls = sessionmaker(bind=engine) #创建与数据库的会话session class ,注意,这里返回给session的是个class,不是实例 23 session = SessionCls() 24 #h1 = Host(hostname='localhost',ip_addr='127.0.0.1') 25 #h2 = Host(hostname='ubuntu',ip_addr='192.168.2.243',port=20000) 26 #h3 = Host(hostname='ubuntu2',ip_addr='192.168.2.244',port=20000) 27 #session.add(h3) 28 #session.add_all( [h1,h2]) 29 #h2.hostname = 'ubuntu_test' #只要没提交,此时修改也没问题 30 #session.rollback() 31 #session.commit() #提交 32 res = session.query(Host).filter(Host.hostname.in_(['ubuntu2','localhost'])).all() 33 print(res)
注:SQLAlchemy无法修改表结构,如果需要可以使用SQLAlchemy开发者开源的另外一个软件Alembic来完成。
步骤三:
使用 ORM/Schema Type/SQL Expression Language/Engine/ConnectionPooling/Dialect 所有组件对数据进行操作。根据类创建对象,对象转换成SQL,执行SQL。
1 from sqlalchemy.ext.declarative import declarative_base 2 from sqlalchemy import Column, Integer, String 3 from sqlalchemy.orm import sessionmaker 4 from sqlalchemy import create_engine 5 6 engine = create_engine("mysql+mysqldb://root:123@127.0.0.1:3306/s11", max_overflow=5) 7 8 Base = declarative_base() 9 10 11 class User(Base): 12 __tablename__ = 'users' 13 id = Column(Integer, primary_key=True) 14 name = Column(String(50)) 15 16 # 寻找Base的所有子类,按照子类的结构在数据库中生成对应的数据表信息 17 # Base.metadata.create_all(engine) 18 19 Session = sessionmaker(bind=engine) 20 session = Session() 21 22 23 # ########## 增 ########## 24 # u = User(id=2, name='sb') 25 # session.add(u) 26 # session.add_all([ 27 # User(id=3, name='sb'), 28 # User(id=4, name='sb') 29 # ]) 30 # session.commit() 31 32 # ########## 删除 ########## 33 # session.query(User).filter(User.id > 2).delete() 34 # session.commit() 35 36 # ########## 修改 ########## 37 # session.query(User).filter(User.id > 2).update({'cluster_id' : 0}) 38 # session.commit() 39 # ########## 查 ########## 40 # ret = session.query(User).filter_by(name='sb').first() 41 42 # ret = session.query(User).filter_by(name='sb').all() 43 # print ret 44 45 # ret = session.query(User).filter(User.name.in_(['sb','bb'])).all() 46 # print ret 47 48 # ret = session.query(User.name.label('name_label')).all() 49 # print ret,type(ret) 50 51 # ret = session.query(User).order_by(User.id).all() 52 # print ret 53 54 # ret = session.query(User).order_by(User.id)[1:3] 55 # print ret 56 # session.commit()
外键关联
1 from sqlalchemy import Table, Column, Integer, ForeignKey 2 from sqlalchemy.orm import relationship 3 from sqlalchemy.ext.declarative import declarative_base 4 5 Base = declarative_base()
1 class Parent(Base): 2 __tablename__ = 'parent' 3 id = Column(Integer, primary_key=True) 4 children = relationship("Child") 5 6 class Child(Base): 7 __tablename__ = 'child' 8 id = Column(Integer, primary_key=True) 9 parent_id = Column(Integer, ForeignKey('parent.id'))
不同于上面的一对多,下面增加了语句 relationship
class Parent(Base): __tablename__ = 'parent' id = Column(Integer, primary_key=True) children = relationship("Child", back_populates="parent") class Child(Base): __tablename__ = 'child' id = Column(Integer, primary_key=True) parent_id = Column(Integer, ForeignKey('parent.id')) parent = relationship("Parent", back_populates="children")
SqlAchemy关联Join查询
- INNER JOIN: 可以说是返回两个表的交集;
- LEFT JOIN: 返回左边表的所有行,而仅仅返回右边表和左边表相匹配的行;
- RIGHT JOIN: 返回右边表的所有行,而仅仅返回左边表和右边表相匹配的行;
具体的区别参见:http://stackoverflow.com/questions/38549/difference-between-inner-and-outer-joins
group by 查询:
1 select name,count(host.id) as NumberOfHosts from host right join host_group on host.id= host_group.host_id group by name;
in SQLAchemy
1 from sqlalchemy import func 2 session.query(HostGroup, func.count(HostGroup.name )).group_by(HostGroup.name).all() 3 4 #another example 5 session.query(func.count(User.name), User.name).group_by(User.name).all() SELECT count(users.name) AS count_1, users.name AS users_name 6 FROM users GROUP BY users.name
SqlAchemy中进行关联查询的几个步骤: