SqlAlchemy使用教程(三) CoreAPI访问与操作数据库详解

news2025/2/26 12:24:31

在这里插入图片描述

  • SqlAlchemy使用教程(一) 原理与环境搭建
  • SqlAlchemy使用教程(二) 入门示例及编程步骤

三、使用Core API访问与操作数据库

Sqlalchemy 的Core部分集成了DB API, 事务管理,schema描述等功能,ORM构筑于其上。本章介绍创建 Engine对象,使用基本的 Sql Express Language 方法,以及如何实现对数据库的CRUD操作等内容。

1、创建DB engine 对象

1.1创建database engine 对象

Engine 是db连接管理类,
语法:

from sqlalchemy import create_engine
#创建引擎对象
engine = create_engine("sqlite:///:memory:", echo=True)
#连接数据库
conn = engine.connect()

Sqlalchemy.create_engine( ) 方法第1个参数是db连接表达式,格式为:

dialect[+driver]://user:password@host/dbname
  • dialect 通常为数据库类型,如sqlite, mysql, mongodb, etc.
  • driver 是python 访问数据库的包。
    如 sqlite+sqlite3, mysql+mysqlconnector

1.2 连接至各类数据库的配置

1.2.1 sqlite 连接

上面示例是sqlite的连接表达式。 Driver是python访问数据库的DBAPI库。

e = create_engine('sqlite:///path/to/database.db')

如果是绝对地址 sqlite:usr/local/myproject/database.db

:memory 表示使用内存数据库,不保存在硬盘。
对于windows 系统,

e = create_engine('sqlite:///C:\\myapp\\db\\main.db')
1.2.2 连接mysql

Mysql 的DBAPI,常用的有PyMysql 与 mysql-connector,其连接表达式分别为:

mysql+pymysql://root:123456@192.168.99.240:3306/testdb
mysql+mysqlconnector://roprot:123456@192.168.99.240:3306/testdb
1.2.3 连接PostgreSQL

通常使用的接口库为 psycopg2

postgresql+psycopg2://user:password@host:port/dbname[?key=value&key=value...]

engine = create_engine(
    "postgresql+psycopg2://scott:tiger@localhost/test",
    isolation_level="SERIALIZABLE",
)

Ssl连接

engine = sa.create_engine(
   "postgresql+psycopg2://scott:tiger@192.168.0.199:5432/test?sslmode=require"
)
1.2.4 连接MongoDB
engine = create_engine("mongodb:///?Server=MyServer&Port=27017&Database=test&User=test&Password=Password")

定义1个mapping类
base = declarative_base()
class restaurants(base):
__tablename__ = "restaurants"
borough = Column(String,primary_key=True)
cuisine = Column(String)

查询:

engine=create_engine("mongodb:///?Server=MyServer&Port=27017&Database=test&User=test&Password=Password")
factory = sessionmaker(bind=engine)
session = factory()
for instance in session.query(restaurants).filter_by(Name="Morris Park Bake Shop"):
print("borough: ", instance.borough)
print("cuisine: ", instance.cuisine)
print("---------")

1.3创建connect 对象

语法:

conn = engine.connect() 

e = create_engine('sqlite:///C:\\myapp\\db\\main.db')
conn = e.connect()

推荐使用context with 语法使用connect对象

from sqlalchemy import create_engine, text
engine = create_engine('sqlite:///C:\\myapp\\db\\main.db')
with engine.connect() as connection:
    result = connection.execute(text("select username from users"))
    for row in result:
        print("username:", row["username"])

如果修改了数据,应调用 conn.commit() 提交transaction

2. SQL Express Language 常用方法

Sqlalchemy 对sql进行了封装,其SQL Express语法比直接使用sql 语句更方便,优势是传参与获取返回值更省事。

2.1 使用 text() 生成SQL Express语句

text()方法是CoreAPI中最基础的方法之一,主要作用,用于封装 sql 语句

from sqlalchemy import text

t_sql = text("SELECT * FROM users")
result = connection.execute(t_sql)

传参:

t_sql = text("SELECT * FROM users WHERE id=:user_id")
result = connection.execute(t_sql, { ‘user_id’: 12 } )

如果使用r” “ ,则用 : 来表示:

2.2 bindparams() 方法传参

也可以通过 text(sql_statement).bindparams() 直接构建完整的SQL语句

from sqlalchemy import text, bindparams
stmt = text("SELECT id, name FROM user WHERE name=:name "
            "AND timestamp=:timestamp")
stmt = stmt.bindparams(name='jack',
            timestamp=datetime.datetime(2012, 10, 8, 15, 12, 5)
)
result = conn.execute(stmt)
print(result.all())

bindparams()中可添加参数Type检查:

from sqlalchemy import text
stmt = text("SELECT id, name FROM user WHERE name=:name "
            "AND timestamp=:timestamp")
stmt = stmt.bindparams(
    bindparam('name', type_=String),
    bindparam('timestamp', type_=DateTime)
)
stmt = stmt.bindparams(name='jack',
            timestamp=datetime.datetime(2012, 10, 8, 15, 12, 5))
result = conn.execute(stmt)
print(result.all())

3, 解析查询结果

查询结果类型为 sqlalchemy.engine.Result 类,是1个由 object 组成的列表。可以用多种方法访问:

  • all() , return all rows in a list
  • columns(‘col_1’, ‘col_2’) 指定返回每row 的字段, iterable
  • fetchall(), fetchone(), fetchmany()
  • first() 返回第1行。
  • keys() 返回row的字段名, 是iterable 类型
  • mappings(), 列表元素为dict类型,
  • result.close() 关闭result对象

说明:

  • 遍历查询结果, all()- , fetchall(), fetchmany(), columns(), 结果为: list[tuple,…], 或iterable,
  • 对row 字段, 可以用key, index , row[0], row[‘id’], row[‘name’], 也可以用row.name , 如
result = conn.execute(text("select x, y from some_table"))
for row in result:
    print(f"Row: {row.x} {row.y}")
  • result.mapping() 返回结果的row 类型为dict,
result = conn.execute(text("select x, y from some_table"))
for dict_row in result.mappings():
    x = dict_row["x"]
    y = dict_row["y"]

4. 使用connect 对象执行CRUD操作

SqlAlchemy可以用connect对象与 session 对象来执行SQL express
connect对象是直接调用DBAPI执行SQL语句,这是使用SqlAlchemy 最简单的方式,同时支持部分Sqlalchemy 的SQL Express 封装语法,但执行的SQL语句依然还要符合各数据库的接口库要求。
Session对象则实现了同1套接口适用于所有数据库。但主要用于ORM API方式。

connect对象操作数据库的好处:可使用text()方法生成SQL语句,利用bindparams() 传值,以及做类型检查。同时支持多线程访问数据库。

创建表的方法,前面已讲过。 下面示例为 insert, update, delete 操作

# insert row 
print("-"*50+"Insert operation")
stmt = text("INSERT INTO some_table VALUES(:x, :y)").bindparams(x=6,y=19)
with engine.connect() as conn:
    conn.execute(stmt)
    conn.commit()
    result = conn.execute( text("select * from some_table") )
    print(result.all())

# update row 
print("-"*50+"update operation")
stmt = text("UPDATE some_table SET y=:y WHERE x=:x").bindparams(y=99,x=5)
with engine.connect() as conn:
    conn.execute(stmt)
    conn.commit()
    result = conn.execute( text("select * from some_table") )
    print(result.all())

# delete row 
print("-"*50+"delete operation")
stmt = text("DELETE FROM some_table WHERE x=:x").bindparams(x=4)
with engine.connect() as conn:
    conn.execute(stmt)
    conn.commit()
    result = conn.execute( text("select * from some_table") )
    print(result.rowcount)
    print(result.all())

output:

--------------------------------------------------Insert operation
2023-12-03 15:50:36,978 INFO sqlalchemy.engine.Engine BEGIN (implicit)
2023-12-03 15:50:36,978 INFO sqlalchemy.engine.Engine INSERT INTO some_table VALUES(?, ?)
2023-12-03 15:50:36,978 INFO sqlalchemy.engine.Engine [generated in 0.00085s] (6, 19)
2023-12-03 15:50:36,979 INFO sqlalchemy.engine.Engine COMMIT
2023-12-03 15:50:36,980 INFO sqlalchemy.engine.Engine BEGIN (implicit)
2023-12-03 15:50:36,980 INFO sqlalchemy.engine.Engine select * from some_table
2023-12-03 15:50:36,981 INFO sqlalchemy.engine.Engine [generated in 0.00132s] ()
[(1, 1), (2, 4), (3, 10), (4, 11), (5, 25), (6, 19)]
2023-12-03 15:50:36,982 INFO sqlalchemy.engine.Engine ROLLBACK
--------------------------------------------------update operation
 [(1, 1), (2, 4), (3, 10), (4, 11), (5, 99), (6, 19)]
2023-12-03 15:50:36,985 INFO sqlalchemy.engine.Engine ROLLBACK
--------------------------------------------------delete operation
[(1, 1), (2, 4), (3, 10), (5, 99), (6, 19)]
2023-12-03 15:50:36,989 INFO sqlalchemy.engine.Engine ROLLBACK

5. 表间关系处理

Sqlalchemy 使用DBAPI处理表间关系语法是依据数据库规定, 但基本均支持标准SQL语法

5.1 创建外键字段的语法:

 CREATE TABLE tracks(
      ……
  trackartist   INTEGER,     -- 外键字段
FOREIGN KEY(trackartist) REFERENCES artist(artistid)
)

辅表artist.id字段须为主键或unique index。

5.2 各种表间关系的实现方式:

  • One to one: 还是用 foreign key来实现。
  • One to many: 就是外键
  • Many to many: 需要中间表, 用2个foreign key 与两张表分别建立 one to many 关系。

示例 :

import sqlalchemy

from sqlalchemy import create_engine
from sqlalchemy import text
from sqlalchemy.orm import sessionmaker  

engine = create_engine("sqlite:///order.db")

# create table people 
with engine.connect() as conn:
    conn.execute(text("drop table if exists people;"))
    stmt = text("""
        CREATE TABLE people(
                id  integer PRIMARY KEY,
                name TEXT, 
                age  INTEGER
            )
    """ )
    conn.execute(stmt)
    conn.execute(
         text("INSERT INTO people (id,name, age) VALUES (:id,:name, :age)"),
         [ 
            {'id': 1, "name": 'Jack','age':30 }, 
            {'id': 2, "name": 'Smith','age':28 }, 
            {'id': 3, "name": 'Wang','age':35 }, 
          ]
     )
    conn.commit()
    result = conn.execute( text("select * from people") )
    print(result.rowcount)
    print(result.all())

# create table order
# 创建会话(Session)  
with engine.connect() as conn: 
    conn.execute(text("drop table if exists teams"))
    stmt_1 = text("""
        create table teams(
                id  integer PRIMARY KEY,
                team_name  TEXT, 
                pid  integer,
                foreign key (pid) REFERENCES people(id)
        )
    """)
    conn.execute(stmt_1)
    conn.commit()
    conn.execute(
         text("INSERT INTO teams (id, team_name, pid) VALUES (:id, :team_name, :pid)"),
         [ 
            {'id': 101, "team_name": 'TV product','pid':1 }, 
            {'id': 102, "team_name": 'Software development','pid':2 }, 
            {'id': 103, "team_name": 'Electric development','pid':2 }, 
          ]
     )
conn.commit()
    # 跨表查询
    result = conn.execute( text("select a.id, a.team_name, b.name from teams as a left join people as b on a.pid=b.id") )
    print(result.rowcount)
    for row in result.mappings():
        print(row['id'], row['team_name'], row['name'])

6. 通过多线程访问Database

sqlalchemy的engine可做为全局变量, 将connect对象,或 session对象传入线程,实现多线程访问:

示例:

def thread_db(conn,name):
    try:  
        result = conn.execute( text("select * from people") )
        print(result.rowcount)
        print(f"thread {{ name }} result: ")
        print(result.all())
    except Exception as e:
        print("can't open connection object")
    finally: 
        conn.close()

from threading import Thread

t1 = Thread(target=thread_db, args=(engine.connect(),"thread_a"))
t2 = Thread(target=thread_db, args=(engine.connect(),"thread_b"))
t1.start()
t2.start()
t1.join()
t2.join()
print("main thread is ended")
output: 
thread { name } result:
thread { name } result:
[(1, 'Jack', 30), (2, 'Smith', 28), (3, 'Wang', 35)]
[(1, 'Jack', 30), (2, 'Smith', 28), (3, 'Wang', 35)]
main thread is ended

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1382972.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

「企业架构框架」什么是TOGAF?

什么是TOGAF?TOGAF开发概述什么是TOGAF上下文中的架构?什么是企业架构?TOGAF的结构介绍架构开发方法ADM指南和技术架构内容框架企业连续体和工具参考模型架构能力框架相关链接 什么是TOGAF? TOGAF由开放集团推出,是一种…

LangChain 71 字符串评估器String Evaluation衡量在多样化数据上的性能和完整性

LangChain系列文章 LangChain 60 深入理解LangChain 表达式语言23 multiple chains链透传参数 LangChain Expression Language (LCEL)LangChain 61 深入理解LangChain 表达式语言24 multiple chains链透传参数 LangChain Expression Language (LCEL)LangChain 62 深入理解Lang…

【STK】手把手教你利用STK进行关联分析仿真01-STK/CAT模块介绍

关联分析工具(Conjunction Analysis Tool )主要用于分析航天发射或卫星在轨运行过程中与其他目标之间的接近情况,关联分析包括: 接近分析工具 Close Approach Tool CAT高级接近分析工具 AdvCAT激光接近分析工具 LaserCAT发射窗口分析工具 Launch Window Analysis今天主要介绍…

RAG 评估框架 -- RAGAS

原文 引入 RAG(Retrieval Augmented Generation)的原因 随着ChatGPT的推出,很多人都理所当然直接用LLM当作知识库回答问题。这种想法有两个明显的缺点: LLM无法得知在训练之后所发生的事情,因此无法回答相关的问题存…

大面积光源HUD阳光倒灌实验装置太阳光模拟器

背景 1.根据现在市场上一些量产的hud的结构和原理可知,hud中最重要的零件之一就是凹面镜(自由曲面),hud利用凹面镜放大投影的光学原理进行投影成像。当发生阳光倒灌时,太阳光沿着hud正常工作时成像的逆光路,通过挡风玻璃-凹面镜-…

4.【CPP】入门(初始化列表||explicit||static||友元||静态成员变量/函数)

一.初始化列表 1.引入 我们知道在c11中才能在成员对象声明时初始化,像下面这样。 class Date { public: Date(int year, int month, int day): _year(year), _month(month), _day(day) {} private: int _year2000; int _month12; int _day20; };注意:…

CMake tasks.json launch.json

hehedalinux:~/Linux/cmake/cmakeClass$ tree . ├── CMakeLists.txt ├── include │ ├── Gun.h │ └── Soldier.h ├── main.cpp └── src├── Gun.cpp└── Soldier.cpp2 directories, 6 files hehedalinux:~/Linux/cmake/cmakeClass$ launch.json&am…

每日一题——LeetCode1189.气球的最大数量

方法一 个人方法: 统计text字符串中b、a、l、o、n 这几个字符出现的次数 l和n需要两个才能拼成一个balloon,所以碰到l和o加1,其他字符加2 最后求出出现次数最少的那个字符再除以2就是能拼凑成的单词数量,避免出现小数要使用向下…

godot初学笔记

godot开发工具下载地址 godot下载地址 godot入门视频 godot入门教学b站地址 素材下载地址 素材下载地址 最终成品图 2D3D如何切换 添加2D场景 添加其他节点 添加人物节点 设置人物为接地 给人物添加Sprite 2d 给人物设置材质 解决材质糊的问题 设置材质包切割 在场景中实…

CISP注册信息系统安全认证,2024年1月20日即将开课~想了解点击查看

CISP注册信息系统安全认证 1🈷20日 开课~ 想报名的必须提前预约啦 👇👇👇 课程介绍 本课程包括10个独立的知识域(安全工程与运营、计算环境安全、软件安全开发、网络安全监管、物理与网络通信安全、信息安全保障、信…

杨中科 .NETCORE EFCORE 第一部分 基本使用

一 、什么是EF Core 什么是ORM 1、说明: 本课程需要你有数据库、SOL等基础知识。 2、ORM: ObjectRelational Mapping。让开发者用对象操作的形式操作关系数据库 比如插入: User user new User(Name"admin"Password"123”; orm.Save(user);比如查询: Book b…

自动粘贴文本:高效复制中国邮政编码,提升效率,释放创意

在快节奏的现代生活中,时间就是金钱,效率就是生命。中国邮政EMS,作为您的快递服务首选,一直致力于提供更加便捷、高效的寄递体验。今天,我们隆重推出全新功能——"自动粘贴文本",让您轻松复制邮政…

test-02-test case generate 测试用例生成 EvoSuite 介绍

拓展阅读 junit5 系列 基于 junit5 实现 junitperf 源码分析 Auto generate mock data for java test.(便于 Java 测试自动生成对象信息) Junit performance rely on junit5 and jdk8.(java 性能测试框架。性能测试。压测。测试报告生成。) 拓展阅读 自动生成测试用例 什么…

Centos7 安装与卸载mysql

卸载 ps ajx | grep mysql : 查看当前服务器是否有mysql 没有的话就不需要卸载咯。 centos7 通过yum下载安装包通常是以.rpm为后缀,rpm -qa 可以查看当前服务器上所有的安装包: rpm -qa | grep mysql | xargs yum -y remove :将查询到的mysql…

第三十九周:文献阅读+Transformer

目录 摘要 Abstract 文献阅读:CNN与LSTM在水质预测中的应用 现有问题 提出方法 相关模型 CNN LSTM CNN-LSTM神经网络模型 模型框架 CNN-LSTM神经网络 研究实验 数据集 模型评估指标 数据预处理 实验设计与结果 研究贡献 Transformer Encoder-Dec…

ES6(ECMAScript 6.0)

ES6 学习链接ES6什么是ES6?ECMAScript 和 JavaScript 的关系 ECMAScript各版本新增特性ES6 块级作用域 let 学习链接 ES6简介 ECMAScript简介及特性(科普!很详细!!!!) 20分钟上手ES…

Java多线程并发篇----第十三篇

系列文章目录 文章目录 系列文章目录前言一、Semaphore 信号量二、Semaphore 与 ReentrantLock 区别三、可重入锁(递归锁)四、公平锁与非公平锁前言 前些天发现了一个巨牛的人工智能学习网站,通俗易懂,风趣幽默,忍不住分享一下给大家。点击跳转到网站,这篇文章男女通用,…

【促销定价】背后的算法技术 2 - 数据预处理生成

【促销定价】背后的算法技术 2 - 数据预处理生成 01 数据探查02 数据清洗03 数据聚合04 数据补全05 小结参考文献 导读:在日常生活中,我们经常会遇见线上/线下商家推出各类打折、满减、赠品、新人价、优惠券、捆绑销售等促销活动。一次成功的促销对于消费…

什么类型的企业需要工单系统?适用场景与优势分析

在现代商业中,必须高效地管理与跟踪大量任务和工作流程。对一些企业而言,处理很多订单是一项具有挑战性的任务。此订单可能来自客户需求、内部问题反馈或各种业务流程中的任务分配。可是,如果没有好的解决方法,这类订单可能会致使…