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模块. ...
随机推荐
- (转载)Python一篇学会多线程
Python 一篇学会多线程 链接:https://www.cnblogs.com/yeayee/p/4952022.html 多线程和多进程是什么自行google补脑,廖雪峰官网也有,但是不够简洁 ...
- windows 下使用命令行操作ftp
open 192.168.10.6 (连接到FTP主机) User allan\ftp (用户连接验证,注意这里的用户用到的是FTP服务器端创建的用户名) 123 ...
- ACM_素数环(dfs)
Problem Description: 如图所示,环由n个圆组成. 将自然数1,2,...,n分别放入每个圆中,并且两个相邻圆中的数字总和应为素数. 注意:第一个圆圈的数量应该始终为1. Input ...
- oracle如何实现函数、包、存储过程加密
首先创建一个名称为test1.sql的文件: CREATE OR REPLACE FUNCTION get_date_string RETURN VARCHAR2 AS BEGIN RETURN TO ...
- SpringCloud开发学习总结(七)—— 声明式服务调用Feign(一)
在实践的过程中,我们会发现在微服务架构中实现客户端负载均衡的服务调用技术Spring Cloud Ribbon<SpringCloud开发学习总结(四)—— 客户端负载均衡Ribbon> ...
- Java 线程是什么-渐入佳境
线程:(一)什么是线程 管哥说:程序中有多个执行流就叫多线程.多线程是多任务的一种特别的形式.好处:单个程序可以创建多个并发执行的程序来完成各自的任务.多线程能满足程序员编写高效率的程序来达到充分利用 ...
- Effective Java读书笔记完结啦
Effective Java是一本经典的书, 很实用的Java进阶读物, 提供了各个方面的best practices. 最近终于做完了Effective Java的读书笔记, 发布出来与大家共享. ...
- Android开发中使用数据库时出现java.lang.IllegalStateException: Cannot perform this operation because the connection pool has been closed.
最近在开发一个 App 的时候用到了数据库,可是在使用数据库的时候就出现了一些问题,在我查询表中的一些信息时出现了一下问题: Caused by: java.lang.IllegalStateExce ...
- SOA测试之浏览器插件
1. Chrome HTTP Rest Client 插件: 1.1 Postman: https://chrome.google.com/webstore/detail/postman-rest-c ...
- vuex使用之state访问状态对象
引入vuex1.利用npm包管理工具,进行安装 vuex.在控制命令行中输入下边的命令就可以了. npm install vuex --save 需要注意的是这里一定要加上 –save,因为你这个包我 ...