之前写过一篇博客介绍过sqlalchemy的基本用法,本篇博客主要介绍除增删改查以外SQLAlchemy对数据库表的操作,主要内容有单表操作、一对多操作、多对多操作。

一、单表操作

单表操作的增删改查在上篇博客中已经详细介绍过,这里不再详细介绍,今天主要对数据库查询在详细介绍一下,下面我们先创建表并插入数据。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
#!/usr/bin/env python
# -*- coding: utf-8 -*-
  
from sqlalchemy import and_, or_
from sqlalchemy import create_engine
from sqlalchemy.ext.declarative import declarative_base
from sqlalchemy import Column, Integer, String, ForeignKey, UniqueConstraint, Index
from sqlalchemy.orm import sessionmaker, relationship
engine = create_engine("mysql+pymysql://root:123456@127.0.0.1:3306/mydata", max_overflow=5)
  
Base = declarative_base()
  
class Group(Base):
    __tablename__='group'
    nid = Column(Integer, primary_key=True,autoincrement=True)
    caption = Column(String(32))
  
class User(Base):
    __tablename__='user'
    nid = Column(Integer, primary_key=True,autoincrement=True)
    username = Column(String(32))
    group_id = Column(Integer, ForeignKey('group.nid'))
    group = relationship("Group",backref='uuu'#跟Group表建立关系,方便查询,常和ForeignKey在一起使用
  
def init_table():
    """
    创建表,调用Base类的子类
    :return:
    """
    Base.metadata.create_all(engine)
  
def drop_table():
    Base.metadata.drop_all(engine)
  
init_table()
Session = sessionmaker(bind=engine)
session = Session()
  
# 单表操作:
session.add(Group(caption='dba'))   #往组里添加数据
session.add(Group(caption='dddd'))
session.commit()
  
session.add_all([
    User(username='jack1',group_id=1),
    User(username='jack2',group_id=1),
    User(username='jack1',group_id=2),
    User(username='jack1',group_id=1),
    User(username='jack2',group_id=1),
])
session.commit()

1,条件查询

1
2
3
4
5
6
7
8
9
#查询用户jack1的nid,filter和filter_by两种书写方式
ret1 = session.query(User.nid).filter(User.username=='jack1').all()
print(ret1)
ret2 = session.query(User.nid).filter_by(username='jack1').all()
print(ret2)
 
#结果:
[(1,), (3,), (4,)]
[(1,), (3,), (4,)]
1
2
3
4
5
6
7
8
9
10
11
12
13
#查询用户nid大于1并且username等于jack2的nid
ret1 = session.query(User.nid).filter(User.nid >1,User.username=='jack2').all()
print(ret1)
 
#结果:
[(2,), (5,)]
 
#查询nid在1和3之间username等于jack1的所有信息
ret2=session.query(User.nid,User.username).filter(User.nid.between(1,3),User.username=='jack1').all()
print(ret2)
 
#结果:
[(1, 'jack1'), (3, 'jack1')]
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
#查询用户nid在1,3,4这个列表里的用户信息
ret=session.query(User.nid,User.username).filter(User.nid.in_([1,3,4])).all()
print(ret)
   
#结果:
[(1, 'jack1'), (3, 'jack1'), (4, 'jack1')]
   
#取反,查询用户nid不在1,3,4这个列表里的用户信息
ret1=session.query(User.nid,User.username).filter(~User.nid.in_([1,3,4,])).all()
print(ret1)
   
#结果:
[(2, 'jack2'), (5, 'jack2')]
  
#查询username='jack1'的所有信息
ret2 = session.query(User.nid,User.username).filter(
User.nid.in_(session.query(User.nid).filter_by(username='jack1'))).all()
print(ret2)
  
#结果:
[(1, 'jack1'), (3, 'jack1'), (4, 'jack1')]
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
#查询nid大于3并且username='jack1'的信息
ret = session.query(User.nid,User.username).filter(and_(User.nid >3,User.username=='jack1')).all()
print(ret)
 
#结果:
[(4, 'jack1')]
 
#查询nid小于2或者username等于jack1的数据
ret = session.query(User.nid,User.username).filter(
or_(User.nid < 2, User.username == 'jack1')).all()
print(ret)
 
#查询用户nid小于2或者username等于jack1并且nid大于3的信息
ret = session.query(User.nid,User.username).filter(
    or_(User.nid < 2,and_(User.username == 'jack1', User.nid > 3))).all()
print(ret)
 
#结果:
[(1, 'jack1'), (4, 'jack1')]

二、通配符

1
2
3
4
5
6
7
8
9
10
11
12
13
#模糊匹配用户名以字母j开头的所有数据
ret = session.query(User.nid,User.username).filter(User.username.like('j%')).all()
 
#结果:
[(1, 'jack1'), (2, 'jack2'), (3, 'jack1'), (4, 'jack1'), (5, 'jack2')]
 
#取反
ret1 = session.query(User.nid,User.username).filter(~User.username.like('j%')).all()
print(ret)
print(ret1)
 
#结果:
[]

三、限制

1
2
3
4
5
ret=session.query(User.nid,User.username)[1:2]
print(ret)
 
#结果:
[(2, 'jack2')]

四、排序

1
2
3
4
5
6
7
8
9
10
11
12
13
#倒序排序
ret=session.query(User.nid,User.username).order_by(User.nid.desc()).all()
print(ret)  
 
#结果:
[(5, 'jack2'), (4, 'jack1'), (3, 'jack1'), (2, 'jack2'), (1, 'jack1')]
 
#正序排序
ret1=session.query(User.nid,User.username).order_by(User.nid.asc()).all()
print(ret1)
 
#结果:
[(1, 'jack1'), (2, 'jack2'), (3, 'jack1'), (4, 'jack1'), (5, 'jack2')]

五、分组

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
#导入模块
from sqlalchemy.sql import func
  
ret = session.query(User.nid,User.username).group_by(User.nid).all()
print(ret)
  
#结果:
[(1, 'jack1'), (2, 'jack2'), (3, 'jack1'), (4, 'jack1'), (5, 'jack2')]
  
ret1=session.query(
    func.max(User.nid),
    func.sum(User.nid),
    func.min(User.nid),).group_by(User.username).all()
print(ret1)
  
#结果:
[(4, Decimal('8'), 1), (5, Decimal('7'), 2)]
  
ret2=session.query(
    func.max(User.nid),
    func.sum(User.nid),
    func.min(User.nid), ).group_by(User.username).having(func.min(User.nid)>1).all()
print(ret2)
  
#结果:
[(5, Decimal('7'), 2)]
 
#打印SQL语句:
from sqlalchemy.sql import func
ret2=session.query(
    func.max(User.nid),
    func.sum(User.nid),
    func.min(User.nid), ).group_by(User.username).having(func.min(User.nid)>1)
print(ret2)
 
#结果:
SELECT max("user".nid) AS max_1, sum("user".nid) AS sum_1, min("user".nid) AS min_1
FROM "user" GROUP BY "user".username
HAVING min("user".nid) > :min_2
[('jack1', 'dba'), ('jack2', 'dddd')]
SELECT "user".nid AS user_nid, "user".username AS user_username, "user".group_id AS user_group_id
FROM "user" LEFT OUTER JOIN "group" ON "group".nid = "user".group_id

六、组合

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
q1=session.query(User.username).filter(User.nid >2)
q2=session.query(Group.caption).filter(Group.nid <2)
ret = q1.union(q2).all()
print(ret)
 
#结果:
[('jack1',), ('jack2',), ('dba',)]
 
q1=session.query(User.username).filter(User.nid >2)
q2=session.query(Group.caption).filter(Group.nid <2)
ret = q1.union_all(q2).all()
print(ret)
 
#结果:
[('jack1',), ('jack1',), ('jack2',), ('dba',)]

二、一对多操作

一对多的关系就需要我们外键来进行约束,下面我们来举例来说明一对多进行连表操作。

1,原始方式:通过join方法来进行连表操作。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
ret = session.query(User.username,Group.caption).filter(User.nid==Group.nid).all()
print(ret)
   
#结果:
[('jack1', 'dba'), ('jack2', 'dddd')]
   
#通过join来进行连表操作,加isouter的区别:
sql1 = session.query(User).join(Group,isouter=True)
print(sql1)
   
#结果:
SELECT "user".nid AS user_nid, "user".username AS user_username, "user".group_id AS user_group_id
FROM "user" LEFT OUTER JOIN "group" ON "group".nid = "user".group_id
   
sql2 = session.query(User).join(Group)
print(sql2)
   
#结果:
SELECT "user".nid AS user_nid, "user".username AS user_username, "user".group_id AS user_group_id
FROM "user" JOIN "group" ON "group".nid = "user".group_id
 
#连表操作
ret = session.query(User.username,Group.caption).join(Group,isouter=True).filter(Group.caption == 'dba').all()
print(ret)
 
#结果:
[('jack1', 'dba'), ('jack2', 'dba'), ('jack1', 'dba')]

2,新方式:通过建立relationship的方式

1
2
3
4
5
6
7
#首先在创建表的类中加入relationship字段
class User(Base):
    __tablename__='user'
    nid = Column(Integer, primary_key=True,autoincrement=True)
    username = Column(String(32))
    group_id = Column(Integer, ForeignKey('group.nid'))
    group = relationship("Group",backref='uuu')   #跟Group表建立关系,方便查询,backref为虚拟列

正向查询:通过User表查询Group表

1
2
3
4
5
6
7
8
9
10
11
12
13
ret = session.query(User).all()
for obj in ret:
    #obj代指user表的每一行数据
    #obj.group代指group对象
    print(obj.nid,obj.username,obj.group_id,obj.group_id,obj.group,
          obj.group.nid,obj.group.caption)
 
#结果:
1 jack1 1 1 <__main__.Group object at 0x0000015D762F4630> 1 dba
2 jack2 1 1 <__main__.Group object at 0x0000015D762F4630> 1 dba
3 jack1 2 2 <__main__.Group object at 0x0000015D762F47F0> 2 dddd
4 jack1 1 1 <__main__.Group object at 0x0000015D762F4630> 1 dba
5 jack2 2 2 <__main__.Group object at 0x0000015D762F47F0> 2 dddd

反向查询:通过Group表查询User表

1
2
3
4
5
6
7
8
9
obj = session.query(Group).filter(Group.caption == 'dba').first()
print(obj.nid)
print(obj.caption)
print(obj.uuu)
 
#结果:
1
dba
[<__main__.User object at 0x000002606096C5C0>, <__main__.User object at 0x000002606096C630>, <__main__.User object at 0x000002606096C6A0>]

我们可以看到上面的例子输出的为对象的列表,输出不太友好,为了达到自己想要的结果,我们可以进行自定义返回结果,请看下面代码,加入__repr__函数:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
class User(Base):
    __tablename__='user'
    nid = Column(Integer, primary_key=True,autoincrement=True)
    username = Column(String(32))
    group_id = Column(Integer, ForeignKey('group.nid'))
    group = relationship("Group",backref='uuu'#跟Group表建立关系,方便查询,常和ForeignKey在一起使用
 
    def __repr__(self):
        """
        自定义返回结果
        :return:
        """
        temp = '%s:%s:%s' % (self.nid,self.username,self.group_id)
        return temp

三、多对多操作

1,创建表结构并插入信息

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
#!/usr/bin/env python
# -*- coding: utf-8 -*-
 
from sqlalchemy import create_engine
from sqlalchemy.ext.declarative import declarative_base
from sqlalchemy import Column, Integer, String, ForeignKey, UniqueConstraint, Index
from sqlalchemy.orm import sessionmaker, relationship
engine = create_engine("mysql+pymysql://root:123456@127.0.0.1:3306/mydata", max_overflow=5)
 
Base = declarative_base()
 
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))
 
class HostUser(Base):
    __tablename__ = 'host_user'
    nid = Column(Integer, primary_key=True,autoincrement=True)
    username = Column(String(32))
 
#使用for循环时,通过正向反向查询
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'))
 
 
    host = relationship("Host",backref='h')
    host_user = relationship("HostUser",backref='u')
 
def init_table():
    """
    创建表,调用Base类的子类
    :return:
    """
    Base.metadata.create_all(engine)
 
def drop_table():
    Base.metadata.drop_all(engine)
 
init_table()
Session = sessionmaker(bind=engine)
session = Session()
 
session.add_all([
    Host(hostname='c1',port='22',ip='1.1.1.1'),
    Host(hostname='c2',port='22',ip='1.1.1.2'),
    Host(hostname='c3',port='22',ip='1.1.1.3'),
    Host(hostname='c4',port='22',ip='1.1.1.4'),
    Host(hostname='c5',port='22',ip='1.1.1.5'),
])
session.commit()
 
 
session.add_all([
    HostUser(username='root'),
    HostUser(username='db'),
    HostUser(username='nb'),
    HostUser(username='sb'),
])
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()

2,需求:获取主机1中所有的用户

 方法一:通过一步一步取

1
2
3
4
5
6
7
8
9
10
11
12
host_obj = session.query(Host).filter(Host.hostname == 'c1').first()
# #取出host_obj.nid
host_to_host_user = session.query(HostToHostUser.host_user_id).filter(HostToHostUser.host_id== host_obj.nid).all()
#
# #因为取出来的结果是[(1,),(2,),(3,)],我们通过内置函数zip来转换成想要的结果
r = zip(*host_to_host_user)
#
users =session.query(HostUser.username).filter(HostUser.nid.in_(list(r)[0])).all()
print(users)
 
#结果:
[('root',), ('db',), ('nb',)]

方法二:通过join的方式

1
2
#通过代码整合的代码,相当复杂
session.query(HostUser.name).filter(HostUser.nid.in_(session.query(HostToHostUser.host_user_id).filter(HostToHostUser.host_id == session.query(Host.nid).filter(Host.hostname == 'c1'))))

方法三:通过建立relationship的方式

 1,对象

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
#!/usr/bin/env python
# -*- coding: utf-8 -*-
 
from sqlalchemy import create_engine
from sqlalchemy.ext.declarative import declarative_base
from sqlalchemy import Column, Integer, String, ForeignKey, UniqueConstraint, Index
from sqlalchemy.orm import sessionmaker, relationship
engine = create_engine("mysql+pymysql://root:123456@127.0.0.1:3306/mydata", max_overflow=5)
 
Base = declarative_base()
 
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=HostToHostUser.__table__,backref='h')
 
# host_user = relationship('HostUser', secondary=lambda: HostToHostUser.__table__, backref='h')
#这里加lambda是因为关系表在下面,可以不加lambda,但是关系表要放上面
 
 
class HostUser(Base):
    __tablename__ = 'host_user'
    nid = Column(Integer, primary_key=True,autoincrement=True)
    username = Column(String(32))
 
def init_table():
    """
    创建表,调用Base类的子类
    :return:
    """
    Base.metadata.create_all(engine)
 
def drop_table():
    Base.metadata.drop_all(engine)
 
Session = sessionmaker(bind=engine)
session = Session()
 
host_obj= session.query(Host).filter(Host.hostname=='c1').first()
print(host_obj.host_user)

2,类

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
#!/usr/bin/env python
# -*- coding: utf-8 -*-
 
from sqlalchemy import create_engine
from sqlalchemy.ext.declarative import declarative_base
from sqlalchemy import Column, Integer, String, ForeignKey, UniqueConstraint, Index
from sqlalchemy.orm import sessionmaker, relationship
engine = create_engine("mysql+pymysql://root:123456@127.0.0.1:3306/mydata", max_overflow=5)
 
Base = declarative_base()
 
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=HostToHostUser.__table__,backref='h')
 
# host_user = relationship('HostUser', secondary=lambda: HostToHostUser.__table__, backref='h')
#这里加lambda是因为关系表在下面,可以不加lambda,但是关系表要放上面
 
 
class HostUser(Base):
    __tablename__ = 'host_user'
    nid = Column(Integer, primary_key=True,autoincrement=True)
    username = Column(String(32))
 
def init_table():
    """
    创建表,调用Base类的子类
    :return:
    """
    Base.metadata.create_all(engine)
 
def drop_table():
    Base.metadata.drop_all(engine)
 
Session = sessionmaker(bind=engine)
session = Session()
 
host_obj= session.query(Host).filter(Host.hostname=='c1').first()
print(host_obj.host_user)

今天SQLALchemy就介绍到这里,更多参考信息请参考:

SQLAlchmy模块详解的更多相关文章

  1. Python中操作mysql的pymysql模块详解

    Python中操作mysql的pymysql模块详解 前言 pymsql是Python中操作MySQL的模块,其使用方法和MySQLdb几乎相同.但目前pymysql支持python3.x而后者不支持 ...

  2. python之OS模块详解

    python之OS模块详解 ^_^,步入第二个模块世界----->OS 常见函数列表 os.sep:取代操作系统特定的路径分隔符 os.name:指示你正在使用的工作平台.比如对于Windows ...

  3. python之sys模块详解

    python之sys模块详解 sys模块功能多,我们这里介绍一些比较实用的功能,相信你会喜欢的,和我一起走进python的模块吧! sys模块的常见函数列表 sys.argv: 实现从程序外部向程序传 ...

  4. python中threading模块详解(一)

    python中threading模块详解(一) 来源 http://blog.chinaunix.net/uid-27571599-id-3484048.html threading提供了一个比thr ...

  5. python time 模块详解

    Python中time模块详解 发表于2011年5月5日 12:58 a.m.    位于分类我爱Python 在平常的代码中,我们常常需要与时间打交道.在Python中,与时间处理有关的模块就包括: ...

  6. python time模块详解

    python time模块详解 转自:http://blog.csdn.net/kiki113/article/details/4033017 python 的内嵌time模板翻译及说明  一.简介 ...

  7. 小白的Python之路 day5 time,datatime模块详解

    一.模块的分类 可以分成三大类: 1.标准库 2.开源模块 3.自定义模块 二.标准库模块详解 1.time与datetime 在Python中,通常有这几种方式来表示时间:1)时间戳 2)格式化的时 ...

  8. 小白的Python之路 day5 random模块和string模块详解

    random模块详解 一.概述 首先我们看到这个单词是随机的意思,他在python中的主要用于一些随机数,或者需要写一些随机数的代码,下面我们就来整理他的一些用法 二.常用方法 1. random.r ...

  9. Python中time模块详解

    Python中time模块详解 在平常的代码中,我们常常需要与时间打交道.在Python中,与时间处理有关的模块就包括:time,datetime以及calendar.这篇文章,主要讲解time模块. ...

随机推荐

  1. (转载)Python一篇学会多线程

    Python 一篇学会多线程 链接:https://www.cnblogs.com/yeayee/p/4952022.html  多线程和多进程是什么自行google补脑,廖雪峰官网也有,但是不够简洁 ...

  2. windows 下使用命令行操作ftp

    open 192.168.10.6     (连接到FTP主机) User allan\ftp            (用户连接验证,注意这里的用户用到的是FTP服务器端创建的用户名) 123     ...

  3. ACM_素数环(dfs)

    Problem Description: 如图所示,环由n个圆组成. 将自然数1,2,...,n分别放入每个圆中,并且两个相邻圆中的数字总和应为素数. 注意:第一个圆圈的数量应该始终为1. Input ...

  4. oracle如何实现函数、包、存储过程加密

    首先创建一个名称为test1.sql的文件: CREATE OR REPLACE FUNCTION get_date_string RETURN VARCHAR2 AS BEGIN RETURN TO ...

  5. SpringCloud开发学习总结(七)—— 声明式服务调用Feign(一)

    在实践的过程中,我们会发现在微服务架构中实现客户端负载均衡的服务调用技术Spring Cloud Ribbon<SpringCloud开发学习总结(四)—— 客户端负载均衡Ribbon> ...

  6. Java 线程是什么-渐入佳境

    线程:(一)什么是线程 管哥说:程序中有多个执行流就叫多线程.多线程是多任务的一种特别的形式.好处:单个程序可以创建多个并发执行的程序来完成各自的任务.多线程能满足程序员编写高效率的程序来达到充分利用 ...

  7. Effective Java读书笔记完结啦

    Effective Java是一本经典的书, 很实用的Java进阶读物, 提供了各个方面的best practices. 最近终于做完了Effective Java的读书笔记, 发布出来与大家共享. ...

  8. Android开发中使用数据库时出现java.lang.IllegalStateException: Cannot perform this operation because the connection pool has been closed.

    最近在开发一个 App 的时候用到了数据库,可是在使用数据库的时候就出现了一些问题,在我查询表中的一些信息时出现了一下问题: Caused by: java.lang.IllegalStateExce ...

  9. SOA测试之浏览器插件

    1. Chrome HTTP Rest Client 插件: 1.1 Postman: https://chrome.google.com/webstore/detail/postman-rest-c ...

  10. vuex使用之state访问状态对象

    引入vuex1.利用npm包管理工具,进行安装 vuex.在控制命令行中输入下边的命令就可以了. npm install vuex --save 需要注意的是这里一定要加上 –save,因为你这个包我 ...