基础入门_Python-模块和包.深入SQLAlchemy之玩转各种增删查改操作?

增加数据:

# 单行数据(from sqlalchemy import ...)


conn = engine.connect()
# 方式一: 调用表对象的insert
ins = cookies.insert().values(
    cookie_name=‘chocolate chip‘,
    cookie_recipe_url=‘http://some.aweso.me/cookie/recipe.html‘,
    cookie_sku=‘CC01‘,
    quantity=‘12‘,
    unit_cost=‘0.50‘
)
print ‘values: => {0}‘.format(ins.compile().params)
result = conn.execute(ins)
print ‘instid: => {0}‘.format(result.inserted_primary_key)
# 方式二: 调用全局对象insert
ins = insert(cookies).values(
    cookie_name=‘chocolate chip‘,
    cookie_recipe_url=‘http://some.aweso.me/cookie/recipe.html‘,
    cookie_sku=‘CC01‘,
    quantity=‘12‘,
    unit_cost=‘0.50‘
)
print ‘values: => {0}‘.format(ins.compile().params)
result = conn.execute(ins)
print ‘instid: => {0}‘.format(result.inserted_primary_key)
# 方式三: 调用execute中执行
ins = cookies.insert()
result = conn.execute(
    ins,
    cookie_name=‘chocolate chip‘,
    cookie_recipe_url=‘http://some.aweso.me/cookie/recipe.html‘,
    cookie_sku=‘CC01‘,
    quantity=‘12‘,
    unit_cost=‘0.50‘
)
print ‘values: => {0}‘.format(ins.compile().params)
result = conn.execute(ins)
print ‘instid: => {0}‘.format(result.inserted_primary_key)


说明: 如上演示了三种添加数据的方式,如第一种调用,指定表的inset()初始化一个insert实例,然后调用其values方法来填充默认insert语句的中的列对应的值,最终返回一个insert对象,通过ins.compile().params可通过字典的形式返回插入的键值对,最终调用conn连接对象的execute执行这个ins对象compile翻译后的SQL语句,返回执行结果对象,还可以通过结果对象result.inserted_primary_key返回插入记录的ID列表

# 多行数据(from sqlalchemy import ...)


conn = engine.connect()
inventory_list = [
    {
        ‘cookie_name‘: ‘peanut butter‘,
        ‘cookie_recipe_url‘: ‘http://some.aweso.me/cookie/peanut.html‘,
        ‘cookie_sku‘: ‘PB01‘,
        ‘quantity‘: ‘24‘,
        ‘unit_cost‘: ‘0.25‘
    },
    {
        ‘cookie_name‘: ‘oatmeal raisin‘,
        ‘cookie_recipe_url‘: ‘http://some.okay.me/cookie/raisin.html‘,
        ‘cookie_sku‘: ‘EWW01‘,
        ‘quantity‘: ‘100‘,
        ‘unit_cost‘: ‘1.00‘
    }
]
ins = insert(cookies)
result = conn.execute(ins, inventory_list)
print ‘instid: {0}‘.format(result.lastrowid)


说明: 如上演示了最常用的多行插入数据的方式,conn.execute返回的ResultProxy对象在多行插入时可以通过result.lastrowid来获取插入最后一行的id值

查询数据:



# 所有字段(from sqlalchemy import ...)


conn = engine.connect()
# 方式一: 调用全局对象select
s = select([
    cookies.c.id, cookies.c.cookie_name, cookies.c.cookie_recipe_url,
    cookies.c.cookie_sku, cookies.c.quantity, cookies.c.unit_cost
])
r = conn.execute(s)
k = r.keys()
result = [dict(zip(k, v)) for v in r.fetchall()]
print ‘values: {0}‘.format(result)
# 方式二: 调用表级对象select
s = cookies.select()
r = conn.execute(s)
k = r.keys()
result = [dict(zip(k, v)) for v in r.fetchall()]
print ‘values: {0}‘.format(result)


说明: 如上演示了两种查询数据的方式,首先实例化,如第一种调用,一个select实例,实例参数必须是一个列表,如果列表中为表名则表示查询所有列,否则查询指定列,cookies.c.id其实就是column(id)对象,然后调用conn.execute执行这个select对象compile翻译后的SQL语句,然后返回ResultProxy对象,然后调用ResultProxy对象的fetchall来获取所有行,ResultProxy对象有一个特殊的方法keys()可获取所有的列名,有时模版渲染时字典形式比较方便.

# 结果对象(from sqlalchemy import ...)


conn = engine.connect()
s = select([
    cookies.c.id, cookies.c.cookie_name, cookies.c.cookie_recipe_url,
    cookies.c.cookie_sku, cookies.c.quantity, cookies.c.unit_cost
])
# 说明: r为ResultProxy是cursor代理,而cursor是支持迭代的,更加推荐迭代获取结果集
r = conn.execute(s)
for record in r:
    print ‘type => {} values => {}‘.format(type(record), record)
# 说明: r.fetchall()返回是列表,但列表中的每个元素通过分片后会自动转换为RowProxy对象
r = conn.execute(s)
# Get a wrapper of cursor, ResultProxy
print ‘type => {}‘.format(type(r))
# Get all row of the ResultProxy, list
allrows = r.fetchall()
print ‘type => {} values => {}‘.format(type(allrows), allrows)
# Get one row of the list, RowProxy
onerow = allrows[0]
print ‘type => {} values => {}‘.format(type(onerow), onerow)
# 说明: cookies.c为cookies中虽有的列对象集合,可通过遍历通过.或[]来获取对应列的值
# Get all col of the row, value
for key in cookies.c:
    oneval = getattr(onerow, key.name)
    print ‘type => {} values => {}‘.format(type(oneval), oneval)
# 说明: r.fetchone每次获取的是从上一次fetch的位置算起的第一个,且返回的也是RowProxy对象
r = conn.execute(s)
onerow = r.fetchone()
print ‘type => {} values => {}‘.format(type(onerow), onerow)
# 说明: r.first()永远返回结果集中的第一条记录,且返回的是RowProxy对象
r = conn.execute(s)
firstrow = r.first()
print ‘type => {} values => {}‘.format(type(firstrow), firstrow)
# 说明: r.scalar()永远返回结果集中的第一条记录的第一列的值,返回一行时才有意义
r = conn.execute(s)
ids = r.scalar()
print ‘type => {} values => {}‘.format(type(ids), ids)


说明: 如上演示了多种代理结果集的操作方法,比较有意思的是ResultProxy对象fetchall返回的是元组列表而分片后的元素自动转换为RowProxy对象,还可以通过fetchone/first/scalar等获取,获取到的RowProxy对象可通过.或[表实例.c.列名]的方式获取对应列的值

# 排序相关(from sqlalchemy import ...)


conn = engine.connect()
s = select([cookies.c.quantity, cookies.c.cookie_name]).order_by(desc(cookies.c.quantity))
r = conn.execute(s)
for record in r:
    print ‘{0} - {1}‘.format(record.quantity, record.cookie_name)


说明: 如上演示了常规按照指定列排序操作方法,通过对ResultProxy调用order_by排序,参数为指定列对象,默认正向排序,可通过desc(cookies.c.quantity)或cookies.c.quantity.desc()来逆向排序,但是更推荐使用desc(cookies.c.quantity)这种方式.

# 限制行数(from sqlalchemy import ...)


conn = engine.connect()
s = select([cookies.c.quantity, cookies.c.cookie_name]).order_by(cookies.c.quantity).limit(2)
r = conn.execute(s)
for record in r:
    print ‘{0} - {1}‘.format(record.quantity, record.cookie_name)


说明: 如上演示了按照指定列排序限制行数,通过对ResultProxy调用limit限制行数,参数为限制输出指定行

# 聚合函数(from sqlalchemy.sql import functions)


conn = engine.connect()
# 说明: 总和
s = select([functions.sum(cookies.c.quantity)])
r = conn.execute(s)
print ‘values: {0}‘.format(r.scalar())
# 说明: 计数
s = select([functions.count(cookies.c.id).label(‘inventory_count‘)])
r = conn.execute(s)
result = r.first()
print ‘values: {0}‘.format(result.inventory_count)


说明: 如上演示了常用聚合函数sum和count,sum,默认不使用label定义一个列别名默认用sum_1/count_1...sum_n/count_n作为RowProxy的属性,否则可直接调用result.label_name获取新增列值,当然了比较简单粗暴的方式还是调用scalar,因为它始终会输出最左边列的值

# 各种运算(from sqlalchemy import ...)


conn = engine.connect()
# 说明: 支持几乎PY中所有运算符
s = select([cookies.c.id, (‘xmdevops-‘ + cookies.c.cookie_sku).label(‘cookie_sku_alias‘)])
r = conn.execute(s)
for record in r:
    print type(record), record.items()
# 说明: 支持运算参数灵活的转换
s = select([cookies.c.id, cookies.c.unit_cost.cast(Numeric(12, 2))])
r = conn.execute(s)
for record in r:
    print type(record), record.items()


说明: 如上演示了常用的运算符和一个特殊的转换类型的cast,可以作为column对象的属性调用,也可以直接调用cast,它的最后参数可以是SQLAlchemy支持的任意数据类型

# 过滤数据(from sqlalchemy import ...)


conn = engine.connect()
# expression
s = select([cookies]).where(
    cookies.c.quantity == 12
).where(
    cookies.c.cookie_name == u‘chocolate chip‘
)
r = conn.execute(s)
for record in r:
    print type(record), dict(record.items())
# like / notlike
s = select([cookies]).where(
    cookies.c.cookie_name.like(‘%chocolate%‘)
)
r = conn.execute(s)
for record in r:
    print type(record), dict(record.items())
# between
s = select([cookies]).where(
    cookies.c.id.between(16, 32)
)
r = conn.execute(s)
for record in r:
    print type(record), dict(record.items())
# concat
s = select([cookies]).where(
    cookies.c.id.concat(cookies.c.quantity) == ‘2424‘
)
r = conn.execute(s)
for record in r:
    print type(record), dict(record.items())
# distinct
s = select([cookies.c.cookie_name.distinct()])
r = conn.execute(s)
for record in r:
    print type(record), dict(record.items())
# in_ / notin_
s = select([cookies]).where(
    cookies.c.cookie_name.in_([u‘chocolate chip‘, u‘oatmeal raisin‘])
)
r = conn.execute(s)
for record in r:
    print type(record), dict(record.items())
# is_ / isnot
s = select([cookies]).where(
    cookies.c.cookie_name.is_(None)
)
r = conn.execute(s)
for record in r:
    print type(record), dict(record.items())
# contains
s = select([cookies]).where(
    cookies.c.cookie_name.contains(‘raisin‘)
)
r = conn.execute(s)
for record in r:
    print type(record), dict(record.items())
# endswith
s = select([cookies]).where(
    cookies.c.cookie_name.endswith(‘raisin‘)
)
r = conn.execute(s)
for record in r:
    print type(record), dict(record.items())
# startswith
s = select([cookies]).where(
    cookies.c.cookie_name.startswith(‘chocolate‘)
)
r = conn.execute(s)
for record in r:
    print type(record), dict(record.items())
# and_ / or_ / not_
s = select([cookies]).where(
    and_(cookies.c.quantity > 23, cookies.c.unit_cost < 0.40)
)
r = conn.execute(s)
for record in r:
    print type(record), dict(record.items())


说明: 如上演示了常用的内置函数like/notlike/between/concat/distinct/in_/notin_/is_/isnot/contains/startswith/endswith/and_/or_/not_的操作方法,熟悉MySQL的应该对这些都不陌生吧~这里就不一一讲解了~

更新数据:


conn = engine.connect()
u = update(cookies).where(cookies.c.cookie_name == ‘peanut butter‘).values(
    quantity=cookies.c.quantity * 2
)
r = conn.execute(u)
print ‘values: {0}‘.format(r.rowcount)
s = select([cookies.c.cookie_name, cookies.c.quantity]).where(
    cookies.c.cookie_name == ‘peanut butter‘
)
r = conn.execute(s)
for record in r:
    print type(record), record


说明: 如上演示了常用的更新数据方式,update和insert用法类似,但支持where条件,来限制更新指定列,不然将会更新所有列.

删除数据:


conn = engine.connect()
d = delete(cookies).where(cookies.c.cookie_name == ‘peanut butter‘)
r = conn.execute(d)
print ‘values: {0}‘.format(r.rowcount)


说明: 如上演示了常用的删除数据方式,delete和update/insert的区别在于不需要values,但支持where,来限制删除指定列,不然会删除所有列.

多表连接:


conn = engine.connect()
# 内连接: join,只有两个表相匹配的行才能在结果集中出现
s = select([orders.c.id, users.c.username, line_items.c.quantity, cookies.c.cookie_name]).select_from(
    orders.join(users).join(line_items).join(cookies)
).where(users.c.username == ‘cookiemon‘)
r = conn.execute(s)
for record in r:
    print type(record), dict(record.items())
# 左连接: outerjoin,左边的表不加限制
s = select([line_items.c.id, line_items.c.quantity, cookies.c.cookie_name]).select_from(
    line_items.outerjoin(cookies, line_items.c.cookie_id == cookies.c.id)
)
r = conn.execute(s)
for record in r:
    print type(record), dict(record.items())


说明: 如上演示了常用的自连接join和左连接outerjoin的用法,新版不支持右连接,全连接,但是基本上使用自连接和左连接已经几乎可以满足我们的所有需求了.

表级别名:


conn = engine.connect()
c = cookies.alias()
s = select([c.c.id, cookies.c.cookie_name]).where(
    c.c.id == cookies.c.id
)
r = conn.execute(s)
for record in r:
    print type(record), record


说明: 如上演示了常用的表别名用法,特别是在多表关联时,多处会用到不同的表名,有的表名可能臭长臭长的,不太好记忆,可通过先定义一个别名再操作对应的表~

分组查询:


conn = engine.connect()
s = select([users.c.username, functions.sum(orders.c.id)]).select_from(
    users.join(orders, users.c.id == orders.c.user_id)
).group_by(users.c.username)
r = conn.execute(s)
for record in r:
    print type(record), record


说明: 如上演示了常用的分组查询用法,查询每个用户的订单量,先通过内连接join关联多表查询,然后通过group_by按照用户名来分组,思路和SQL非常类似~

RAWSQL:


conn = engine.connect()
# 全raw sql
s = ‘select * from users‘
r = conn.execute(s)
for record in r:
    print type(record), record
# 半raw sql
s = select([users]).where(text("username=‘limanman‘"))
r = conn.execute(s)
for record in r:
    print type(record), record


说明: 如上演示了常用的裸SQL的用法,其实工作中不太常用,但是有时候SQLALchemy没有实现对应接口时裸SQL也是一种解决方案,如果要半裸状态则需要用text来解析一下先.

时间: 2024-09-28 21:31:20

基础入门_Python-模块和包.深入SQLAlchemy之玩转各种增删查改操作?的相关文章

基础入门_Python-模块和包.深入SQLAlchemy之列级别约束与表级别约束?

简单介绍: 说明: 此模块主要用于将关系型数据库表映射到PY的类,行映射到PY类的实例,列映射为PY实例的属性,由于其兼容众多DB-API及扩展,SO可以优先考虑数据模型,而忽略底层的DB-API切换,数据迁移更方便. 快速安装: pip install --upgrade SQLAlchemy 创建引擎: 1. 连接数据库前需创建引擎,作为执行SQL的接口,其实底层通过Pool(连接池)和Dialect(翻译器)将映射后的PY语句转换为对应DB-API支持的原生SQL语句去执行,这样写PY时就

基础入门_Python-模块和包.深入SQLAlchemy之SQLAlchemy ORM重构表?

简单介绍: 说明: 此模块主要用于将关系型数据库表映射到PY的类,行映射到PY类的实例,列映射为PY实例的属性,由于其兼容众多DB-API及扩展,SO可以优先考虑数据模型,而忽略底层的DB-API切换,数据迁移更方便. 快速安装: pip install --upgrade SQLAlchemy 定义结构: #!/usr/bin/env python # -*- coding: utf-8 -*- """ # # Authors: limanman # OsChina: ht

基础入门_Python-模块和包.深入SQLAlchemy之事务回滚与反射还原对象?

异常处理: # 异常一: AttributeError,对象属性不存在 with engine.connect() as conn:     trans = conn.begin()     s = select([users])     try:         r = conn.execute(s)         for record in r:             print record.Password     except AttributeError, e:         

基础入门_Python-模块和包.运维开发中watchdog事件监视的最佳实践?

简单介绍: 说明:  此模块是一个跨平台的PY库和SHELL工具,可以监视文件系统事件(增加/删除/修改) 快速安装: pip install --upgrade watchdog 日志记录: event_handler = LoggingEventHandler() -> event_handler 说明: 创建一个日志处理句柄,其实LoggingEventHandler是继承自FileSystemEventHandler类,只是重写了增删查改的回调函数,直接调用logging模块写到对应lo

MongoDB入门学习(三):MongoDB的增删查改

对于我们这种菜鸟来说,最重要的不是数据库的管理,也不是数据库的性能,更不是数据库的扩展,而是怎么用好这款数据库,也就是一个数据库提供的最核心的功能,增删查改. 因为MongoDB存储数据都是以文档的模式,所以在操作它的数据时,也是以文档为单位的.那么我们实现增删查改也是以文档为基础,不知道文档是什么的同学可以看看上篇介绍的基本概念. 1.插入文档 向MongoDB集合中插入文档的基本方法是insert: 单个插入 > document = {key : value} > db.collecti

mysql基础知识之增删查改使用介绍

 mysql基础知识之增删查改使用介绍 本文主要介绍mysql常用的SELECT.INSERT.UPDATE.DELETE语句的使用,数据库的安装这里不做介绍,并且事先已经准备好相关数据. 本文中使用的student表中的数据如下: mysql> SELECT * FROM student; 一.SELECT语句的使用 1.单表查询 语法格式: SELECT culom1,culom2,culom3 FROM TABLE_NAME; 可以改变字段显示顺序 2.WHERE子句查询 语法格式: SE

hibernate基础增删查改简单实例

hibernate 基础理论知识网上很多,可以百度和google.这里不做多的介绍,以一个User表来开展例子 建一个web-project 我这里用了junit单元测试环境来进行增删查改的测试,别的不多说,导包就行 本次用到的所有jar包下载地址: 链接:http://pan.baidu.com/s/1skHrg0t 密码:dbe2 1.hibernate配置文件(hibernate.cfg.xml):主要是数据库连接核心的配置项 <?xml version='1.0' encoding='u

mybatis从入门到精通(二) 增删查改

mybatis从入门到精通(二) 增删查改 一丶前言 "增删查改"是后台开发的常用操作, 因此, 学习mybatis或者其他orm框架有必要统一学习一下"增删查改". 二丶准备开发环境 使用"mybatis从入门到精通(一) 入门"准备的开发环境 三丶查 -- <select/> UserMapper.java User selectUser(@Param("userId") int userId); UserMa

基础入门_Python-模块和包.深入Celery之常用架构/方案选型/必知必会?

简单介绍: 说明: 此模块是一个专注于分布式消息传递的异步任务队列,所谓任务就是消息,消息中的有效载荷中包含要执行的任务需要的全部数据 几大特性: 1. Celery易于使用和维护,且不需要配置文件,默认配置启动时自动写入消息代理. 2. Celery高可用,连接丢失或失败时客户端或消费者会自动重试,并且可通过消息代理的双主/主从模式来提高高可用性 3. Celery快速,单个进程每分钟可处理百万任务,且优化后可保持往返延迟在亚毫秒级别 4. Celery灵活,几乎所有部分都支持扩展或单独使用,