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模块. ...
随机推荐
- 【数据结构(C语言版)系列一】 线性表
最近开始看数据结构,该系列笔记简单记录总结下所学的知识,更详细的推荐博主StrayedKing的数据结构系列,笔记部分也摘抄了博主总结的比较好的内容. 一些基本概念和术语 数据是对客观事物的符号表示, ...
- Codeforces Round #459 (Div. 2)C. The Monster
C. The Monster time limit per test 1 second memory limit per test 256 megabytes input standard input ...
- 转-关于UIView的autoresizingMask属性的研究
在 UIView 中有一个autoresizingMask的属性,它对应的是一个枚举的值(如下),属性的意思就是自动调整子控件与父控件中间的位置,宽高. 1 2 3 4 5 6 7 8 9 enum ...
- 里氏替换原则中is和as分别的作用
is 是用于检查对象是否指定类型兼容 if(empls[i] is SE){ ((SE)empls).SayHi(); } as 不用强转可以直接转换 if(empls[i] is SE){ SE s ...
- ASP.NET MVC数据库初始化
public class DBInitializer:DropCreateDatabaseAlways<BookDBContext> { protected override void S ...
- [BZOJ1005][HNOI2008]明明的烦恼 数学+prufer序列+高精度
#include<cstdio> #include<cstring> #include<algorithm> using namespace std; int N; ...
- JS filters-ul li简单过滤
功能要求:在input中输入字母,显示ul li中匹配的元素,隐藏不匹配的 <!DOCTYPE html> <html> <head> <meta chars ...
- Elasticsearch--集群管理_再平衡&预热
目录 控制集群的再平衡 再平衡 集群的就绪 集群再平衡设置 控制再平衡何时开始 控制同时在节点移动的分片数量 控制单个节点上同时初始化的分片数量 控制单个节点上同时初始化的主分片数量 控制分配的分片类 ...
- RDO、SAD、SATD、λ相关概念【转】
率失真优化概述: 率失真优化(Rate D isto r t i on Op t i m ized)策略是在率失真理论[3 ]的基础上提出的一种代价函数方案, RDO 的主要思想是, 在计算代价函数时 ...
- JavaScript——max-age
https://zhidao.baidu.com/question/391047416053664205.html 页面优化方式之一,延长过期时间.默认max-age=0