python 连接操作数据库(二)

时间:2021-09-04 23:13:03

一、我们接着上期的博客继续对ORM框架进行补充,顺便把paramiko模块也给大家讲解一下:

1、ORM框架:

在连接操作数据库的第一个博客中也已经说了,sqlalchemy是一个ORM框架,总结就是:将对象转换成SQL,然后使用数据API执行SQL并获取执行结果。先来看下使用sqlalchemy来链接数据库的基本代码:

 from sqlalchemy.ext.declarative import declarative_base
from sqlalchemy import Column, Integer, String, ForeignKey, UniqueConstraint, Index
from sqlalchemy.orm import sessionmaker, relationship
from sqlalchemy import create_engine engine = create_engine("mysql+pymysql://mysql_test:123456@192.168.163.131:3306/pymysql", max_overflow=5) Base = declarative_base()

首先,前四行是导入的有关模块,我们对这些模块进行简单的介绍,然后列举例子,你就能明白了;

第二行中导入的是Column(字段)、(Integer, String)字段类型、ForeignKey外键、create_engine创建数据库;使用declarative_base模块创建一个Base对象,这个在下面创建表的类中需要继承,在上面的代码中已经事先创建好了pymysql数据库,所以下面我们直接创建表以及插入数据:

 class Host(Base):
__tablename__ = 'host'
h_id = Column(Integer,primary_key=True,autoincrement=True)
host_ip = Column(String(32))
host_port = Column(Integer)
class HostUser(Base):
__tablename__ = 'hostuser'
u_id = Column(Integer,primary_key=True,autoincrement=True)
username = Column(String(32))
password = Column(String(20)) Base.metadata.create_all(engine)

解释说明:

这两个类是用来创建表使用的,每个类对应一个表,在类里面可以定义多个字段,在字段里面的参数可以设置多个(比如:主键、自增等);最后一行才是把类创建成表并存到数据库,当你执行完代码之后,表已经创建了,那么下一步就是添加数据,看下面添加数据的代码:

 Session = sessionmaker(bind=engine)
session = Session() session.add(Host(host_ip = '1.1.1.4',host_port = 5555)) session.add_all([
Host(host_ip = '1.1.1.1',host_port = 22),
Host(host_ip = '1.1.1.2',host_port = 22),
Host(host_ip = '1.1.1.3',host_port = 22),
HostUser(username = 'ma',password = ''),
HostUser(username = 'da',password = ''),
])
session.commit()

插入数据有两种方式,一种是一次插入一条数据,使用的方法是add ; 第二种是一次插入多条数据,使用的方法是add_all;你需要注意的是最后要执行commit方法,不然,你上面做的一切都是白费的,提交不到数据库。

下面看一条查询的语句:

 ret1 = session.query(Host.host_ip,Host.host_port).filter(Host.host_ip == '1.1.1.2').all()
print(ret1) ret2 = session.query(Host.host_ip,Host.host_port).all()
print(ret2) #输出结果
[('1.1.1.2', 22)]
[('1.1.1.1', 22), ('1.1.1.2', 22), ('1.1.1.3', 22), ('1.1.1.4', 5555)]

带filter的是查询一条条件语句,不带条件语句的就查询全部的数据,输出的格式是列表中嵌套元祖。

2、上面说了那么多,其实只是sqlalchemy操作数据库的简单的用法,下面我们说下稍微复杂一点的,连表操作:

一对多

 class  HostUser(Base):
__tablename__ = 'hostuser'
u_id = Column(Integer,primary_key=True,autoincrement=True)
username = Column(String(32))
password = Column(String(20))
host_id = Column(Integer,ForeignKey('host.h_id'))
#创建虚拟关系relationship,跟foreignkey配合使用
host = relationship('Host',backref='hh') session.add_all([
HostUser(username = 'ma',password = '',host_id = 1),
HostUser(username = 'da',password = '',host_id = 2),
])
session.commit()

还有个Host类跟上面是一样的,其实创建这个表的字段也是一样的,只不过在里面增加了一个外键和关系,分别是第六行和第八行,外键的作用就是可以根据特定的字段去查询其它表中的字段,关系的作用下面列举一个例子,你就会明白, 我们先来说下通常我们所做的查询时正向的,什么是正向的呢!就像这个HostUser中有关系,从这个表去其它表中查询数据就是正向的,从其它表中查询数据,但是是通过这个关系去查询的,这样就叫做反向查询,下面我们看个例子:

 #正向查询,有虚拟关系
ret = session.query(HostUser).all()
for obj in ret:
print(obj.username,obj.host.host_ip,obj.host.host_port) 输出结果:
ma 1.1.1.1 22
da 1.1.1.2 22

这个例子说的是有虚拟关系,但是使用的是正向查询,就是利用关系去查询用户所对应的IP地址和端口,下面再说反向查询的原始方式以及有关系的反向查询:

 #反向查询的原始方式
ret1 = session.query(HostUser.u_id,HostUser.username).join(Host,isouter=True).filter(Host.host_ip == '1.1.1.2').all()
print(ret1) #反向查询的虚拟关系查询,需要遍历
obj = session.query(Host).filter(Host.host_ip == '1.1.1.2').first()
print(obj.hh)
for ret in obj.hh:
print(ret.u_id,ret.username)

解释说明:

上面两个例子,第一个是反向查询的原始方式,查询的内容是属于1.1.1.2这台机器的所有用户和对应的用户id;其实使用虚拟关系进行查询就是去掉了join,使用生成的HostUser对象进行调用backref的值hh,就可以查出用户了,两种不同的方式输出的结果的如下:

 [(4, 'da')]
[<__main__.HostUser object at 0x0000000003BBB080>]
4 da

多对多:

多对多的一个关键点是需要第三张表去做关系,下面列举一个例子,来阐述一下,在多对多的查询中使用关系与不使用关系的sql执行:

 engine = create_engine("mysql+pymysql://mysql_test:123456@192.168.163.131:3306/orm_test")
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'))
#多对多操作
host = relationship('Host',backref='h')
host_user = relationship('HostUser',backref='u') 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') class HostUser(Base):
__tablename__ = 'host_user'
nid = Column(Integer, primary_key=True,autoincrement=True)
username = Column(String(32)) Base.metadata.create_all(engine)
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()
'''

先使用类去创建三个表,那个HostToHostUser就是第三张表,用户存放其它两个表的外键和关系的;现在如果要查询c1主机对应的管理员账号,我们如果不用关系的话,应该是这样的:

 #没有关系的原始方式
#1.先在host表中查询c1的nid
host_obj = session.query(Host).filter(Host.hostname=='c1').first()
#2.查询hosttohostuer表中的所有host_id等于c1的nid的对应的host_user_id
host_2_host_user = session.query(HostToHostUser.host_user_id).filter(HostToHostUser.host_id==host_obj.nid).all()
# print(host_2_host_user)
r=zip(*host_2_host_user)
# print(list(list(r)[0]))
#通过查到的host_user_id查询hostuser表中的对应的管理员用户名
users = session.query(HostUser.username).filter(HostUser.nid.in_(list(list(r)[0]))).all()
print(users) #输出结果
[('root',), ('db',), ('nb',)]

里面说的很详细了,我就不再过多的阐述了,下面再看下有关系的查询:

 # 1.反向查找,查询host表中c1的信息,会得到一个对象,对象中存在一个已经设置好的虚拟关系:h
host_obj = session.query(Host).filter(Host.hostname == 'c1').first()
#2.正向查找,遍历对象属性
for item in host_obj.h:
print(item.host_user.username) #输出结果
root
db
nb

怎么样?这个方法是不是简单多了,其实我们在创建表的时候,也创建了一种更简单的方式,那就是把关系放在Host类中,,其实都差不多,都是遍历对象属性得到想要的结果。

python 连接操作数据库(二)的更多相关文章

  1. python 连接操作数据库&lpar;一&rpar;

    一.下面我们所说的就是连接mysql的应用: 1.其实在python中连接操作mysql的模块有多个,在这里我只给大家演示pymysql这一个模块(其实我是感觉它比较好用而已): pymysql是第三 ...

  2. Python连接操作数据库

    步骤: 1.创建与数据库的连接对象: 2.创建游标: 3.通过游标执行语句 4.增删改需要提交(commit)数据 5.关闭连接 如: import MySQLdb   # Python通过MySQL ...

  3. Python——连接操作数据库

    1.安装MySQL驱动程序.下载自动安装包,双击安装即可,非常简单. 2.连接MySQL,下面是Python示例代码. import MySQLdbconn=MySQLdb.connect(host= ...

  4. Python连接MySQL数据库的多种方式

    上篇文章分享了windows下载mysql5.7压缩包配置安装mysql 后续可以选择 ①在本地创建一个数据库,使用navicat工具导出远程测试服务器的数据库至本地,用于学习操作,且不影响测试服务器 ...

  5. pymysql模块使用---Python连接MySQL数据库

    pymysql模块使用---Python连接MySQL数据库 浏览目录 pymysql介绍 连接数据库 execute( ) 之 sql 注入 增删改查操作 进阶用法 一.pymysql介绍 1.介绍 ...

  6. 孤荷凌寒自学python第五十一天初次尝试使用python连接Firebase数据库

    孤荷凌寒自学python第五十一天初次尝试使用python连接Firebase数据库 (完整学习过程屏幕记录视频地址在文末) 今天继续研究Firebase数据库,利用google免费提供的这个数据库服 ...

  7. Python 连接Oracle数据库

    连接:python操作oracle数据库  python——连接Oracle数据库 python模块:cx_Oracle, DBUtil 大概步骤: 1. 下载模块 cx_Oracle (注意版本) ...

  8. MySQL---连接器(python如何操作数据库媒介,基于python语言)

    MySQL — 连接器 连接器的概念 它们往往是一类Python包,或者是一类已经写好的Python库.这些库提供了我们Python去连接数据库服务器的基本功能. ​ 既然它是一个包,那么我们首先学会 ...

  9. 【Python实战】使用Python连接Teradata数据库???未完成

    1.安装Python 方法详见:[Python 05]Python开发环境搭建 2.安装Teradata客户端ODBC驱动 安装包地址:TTU下载地址 (1)安装TeraGSS和tdicu(ODBC依 ...

随机推荐

  1. NDK&lpar;20&rpar;JNI的5大性能缺陷及优化技巧

    转自 : http://www.ibm.com/developerworks/cn/java/j-jni/index.html JNI 编程缺陷可以分为两类: 性能:代码能执行所设计的功能,但运行缓慢 ...

  2. Oracle——事务&lpar;Transaction&rpar;

    事务: 事务是指作为单个逻辑工作单元执行的一组相关操作. 这些操作要求全部完成或者全部不完成. 使用事务的原因:保证数据的安全有效. 事务的四个特点:(ACID) 1.原子性(Atomic):事务中所 ...

  3. codevs2492上帝造题的七分钟 2(线段树)

    /* 区间修改 区间查询 可以用线段树搞 但是一般的标记下放对这个题好像不合适 只能改叶子 然后更新父亲(虽然跑的有点慢) 小优化:如果某个点是1 就不用再开方了 所以搞一个f[i]标记 i 这个点还 ...

  4. sql语句练习题及答案

    表结构 创建表数据    SET NAMES utf8;    SET FOREIGN_KEY_CHECKS = 0;    -- ----------------------------    -- ...

  5. 巧妙解决vue2&period;0关于set添加属性后视图不能更新的问题

    今天在工作中遇到一个问题,郁闷了很久,特地写一篇博客记录一下,方便以后再遇到可以查找,也分享个各位小伙伴,在网上查找很多资料说用Vue.$set设置属性后视图也会更新,但是真相并不是这样,通过等于号赋 ...

  6. 如何使用python在保留原excel格式的前提下插入&sol;修改数据

    一.需求分析: 统计的报表中需要每日查询当天数据并追加到原有的excel后面. 因为原始excel格式已经设定好,如果使用xlwt,仅仅指定设定我们要插入的单元格的格式,原始数据的格式会被初始化. 所 ...

  7. &lbrack;转&rsqb;数据库中间件 MyCAT源码分析——跨库两表Join

    1. 概述 2. 主流程 3. ShareJoin 3.1 JoinParser 3.2 ShareJoin.processSQL(...) 3.3 BatchSQLJob 3.4 ShareDBJo ...

  8. 剑指offer--5&period;用两个栈实现队列

    题目:用两个栈来实现一个队列,完成队列的Push和Pop操作. 队列中的元素为int类型. 思路: # 栈A用来作入队列# 栈B用来出队列,当栈B为空时,栈A全部出栈到栈B,栈B再出栈(即出队列) v ...

  9. 2018&period;12&period;31 bzoj3992&colon; &lbrack;SDOI2015&rsqb;序列统计(生成函数&plus;ntt&plus;快速幂)

    传送门 生成函数简单题. 题意:给出一个集合A={a1,a2,...as}A=\{a_1,a_2,...a_s\}A={a1​,a2​,...as​},所有数都在[0,m−1][0,m-1][0,m− ...

  10. ConcurrentHashMap 扩容分析拾遗

    前言 这是一篇对 transfer 方法的拾遗,关于之前那篇文章的一些一笔带过,或者当时不知道的地方进行回顾. 疑点 1. 为什么将链表拆成两份的时候,0 在低位,1 在高位? 回顾一下 transf ...