SQLAlchmy模块详解
之前写过一篇博客介绍过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 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 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 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 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模块详解的更多相关文章
- Python中操作mysql的pymysql模块详解
Python中操作mysql的pymysql模块详解 前言 pymsql是Python中操作MySQL的模块,其使用方法和MySQLdb几乎相同.但目前pymysql支持python3.x而后者不支持 ...
- python之OS模块详解
python之OS模块详解 ^_^,步入第二个模块世界----->OS 常见函数列表 os.sep:取代操作系统特定的路径分隔符 os.name:指示你正在使用的工作平台.比如对于Windows ...
- python之sys模块详解
python之sys模块详解 sys模块功能多,我们这里介绍一些比较实用的功能,相信你会喜欢的,和我一起走进python的模块吧! sys模块的常见函数列表 sys.argv: 实现从程序外部向程序传 ...
- python中threading模块详解(一)
python中threading模块详解(一) 来源 http://blog.chinaunix.net/uid-27571599-id-3484048.html threading提供了一个比thr ...
- python time 模块详解
Python中time模块详解 发表于2011年5月5日 12:58 a.m. 位于分类我爱Python 在平常的代码中,我们常常需要与时间打交道.在Python中,与时间处理有关的模块就包括: ...
- python time模块详解
python time模块详解 转自:http://blog.csdn.net/kiki113/article/details/4033017 python 的内嵌time模板翻译及说明 一.简介 ...
- 小白的Python之路 day5 time,datatime模块详解
一.模块的分类 可以分成三大类: 1.标准库 2.开源模块 3.自定义模块 二.标准库模块详解 1.time与datetime 在Python中,通常有这几种方式来表示时间:1)时间戳 2)格式化的时 ...
- 小白的Python之路 day5 random模块和string模块详解
random模块详解 一.概述 首先我们看到这个单词是随机的意思,他在python中的主要用于一些随机数,或者需要写一些随机数的代码,下面我们就来整理他的一些用法 二.常用方法 1. random.r ...
- Python中time模块详解
Python中time模块详解 在平常的代码中,我们常常需要与时间打交道.在Python中,与时间处理有关的模块就包括:time,datetime以及calendar.这篇文章,主要讲解time模块. ...
随机推荐
- 187 Repeated DNA Sequences 重复的DNA序列
所有DNA由一系列缩写为A,C,G和 T 的核苷酸组成,例如:“ACGAATTCCG”.在研究DNA时,识别DNA中的重复序列有时非常有用.编写一个函数来查找DNA分子中所有出现超多一次的10个字母长 ...
- 使用Dotfuscator保护.NET DLL加密DLL,防止DLL反编译
1.下载地址 https://pan.baidu.com/s/1ztWlBxw1Qf462AE7hQJQRg 2.操作步骤 2.1安装后打开DotfuscatorPro软件,如下图所示: 2.2 选择 ...
- javascript动态创建div循环列表
动态循环加载列表,实现vue中v-for的效果 效果图: 代码: var noApplicationRecord = document.getElementById('noApplicationRec ...
- 架构师细说 NGINX 的配置及优化
最近感觉很多东西在运用到一定的程度之后,会发现原来是自己了解到的不够.一方面限于实际运用到的不多,一方面可能是因为一开始没有进行全面认识.遂这里搜集整理了一番NGINX. 一.nginx启动和关闭 c ...
- axis2与eclipse的整合:开始一个简单的axis2 的demo
1.下载axis2,现在axis2最新版本是axis2-1.6.2,下载地址:http://axis.apache.org/axis2/java/core/download.cgi 2.下载好的zip ...
- SQL SERVER的数据类型
1.SQL SERVER的数据类型 数据类弄是数据的一种属性,表示数据所表示信息的类型.任何一种计算机语言都定义了自己的数据类型.当然,不同的程序语言都具有不同的特点,所定义的数据类型的各类和名称都或 ...
- Vue 拦截器的使用
拦截器 可以全局进行拦截器设置.拦截器在发送请求前或响应返回时做一些特殊的处理. 拦截器的注册 Vue.http.interceptors.push({ request: function ( req ...
- jQuery核心语法
.each只是处理jQuery对象的方法,jQuery还提供了一个通用的jQuery.each方法,用来处理对象和数组的遍历 jQuery/($).each(array, callback )jQue ...
- 中国版 Office 365 (X-Tenant / Tango) 功能验证报告 - 2 基本步骤
说明: 1. 前期准备 - 在Azure上模拟出生产环境: 包括父域域控.子域域控.父域的Exchange Server.子域的Exchange Server.对Exchange Server, 需要 ...
- servlet 生命周期 与 初始化
一. 生命周期 Servlet 通过调用 init () 方法进行初始化. Servlet 调用 service() 方法来处理客户端的请求. Servlet 通过调用 destroy() 方法终止( ...