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

在这里插入图片描述

  • SqlAlchemy使用教程(一) 原理与环境搭建
  • SqlAlchemy使用教程(二) 入门示例及编程步骤
  • SqlAlchemy使用教程(三) CoreAPI访问与操作数据库详解
  • SqlAlchemy使用教程(四) MetaData 与 SQL Express Language 的使用
  • SqlAlchemy使用教程(五) ORM API 编程入门

三、使用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 textt_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 sqlalchemyfrom 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 Threadt1 = 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.hqwc.cn/news/413055.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

计算机网络——运输层(1)暨小程送书

计算机网络——运输层(1)暨小程送书 小程一言专栏链接: [link](http://t.csdnimg.cn/ZUTXU) 运输层概述两个主要协议运输层和网络层的关系网络层运输层总结 多路复用与多路分解多路复用多路分解不同的技术实现时分复用(TDM)频分复…

C语言从入门到实战——结构体与位段

结构体与位段 前言一、结构体类型的声明1.1 结构体1.1.1 结构的声明1.1.2 结构体变量的创建和初始化 1.2 结构的特殊声明1.3 结构的自引用 二、 结构体内存对齐2.1 对齐规则2.2 为什么存在内存对齐2.3 修改默认对齐数 三、结构体传参四、 结构体实现位段4.1 什么是位段4.2 位段…

【C语言】- 设置控制台文字颜色、大小和字体

【C语言】- 设置控制台标题、编码、文字颜色、大小和字体 文章目录 【C语言】- 设置控制台标题、编码、文字颜色、大小和字体1 - 设置控制台标题2 - 设置控制台编码3 - 设置控制台字体和大小参考链接 1 - 设置控制台标题 因为要用到 Windows API,所以需要包含头文件…

C++大学教程(第九版)5.19求Π的值

题目 代码 #include <bits/stdc.h> using namespace std;int main() {double pai 0;for (int count 1, i 1; count < 1000; i 2, count){int flag 1;if (count % 2 0){flag -1;}pai flag * (4.0 / (i * 1.0));cout << "当取前" << co…

西门子1200和西门子200smart S7通讯

S7通讯是西门子以太网络通讯中最简单最常用的通讯。 下面来介绍200smart和1200之间如何进行S7通讯: 由于200smart和1200使用不同的编程软件&#xff0c;所以只能使用单端组态&#xff0c;我们这里以1200为客服端组态。 1.首先打开博图软件添加1200设备&#xff0c;这里选择1…

(C语言)冒泡排序

一、运行结果&#xff1b; 二、源代码&#xff1b; # define _CRT_SECURE_NO_WARNINGS # include <stdio.h>//实现buble_sort函数&#xff1b; void buble_sort(int arr[], int sz) {//初始化变量值&#xff1b;int i 0;//嵌套循环冒泡排序&#xff1b;//外层循环&…

无人售卖饮品机的优势与选购指南

无人售卖饮品机作为一种新型的自动售货设备&#xff0c;已经越来越受到人们的关注和喜爱。它具有许多优势&#xff0c;为消费者提供了更加便捷、高效的购买体验。同时&#xff0c;面对市场上琳琅满目的无人售卖饮品机&#xff0c;如何挑选适合自己的产品也成为了消费者关心的问…

2018年认证杯SPSSPRO杯数学建模B题(第一阶段)动态模糊图像全过程文档及程序

2018年认证杯SPSSPRO杯数学建模 B题 动态模糊图像 原题再现&#xff1a; 人眼由于存在视觉暂留效应&#xff0c;所以看运动的物体时&#xff0c;看到的每一帧画面都包含了一段时间内 (大约 1/24 秒) 的运动过程&#xff0c;所以这帧画面事实上是模糊的。对电影的截图来说&…

Docker 安装 CentOS

Docker 安装 CentOS CentOS&#xff08;Community Enterprise Operating System&#xff09;是 Linux 发行版之一&#xff0c;它是来自于 Red Hat Enterprise Linux(RHEL) 依照开放源代码规定发布的源代码所编译而成。由于出自同样的源代码&#xff0c;因此有些要求高度稳定性…

rt-thread修改全局中断屏蔽函数,解决内核频繁关闭中断影响精密计时问题

带rtt-nano实时操作系统的小板子需要读取单总线设备&#xff0c;使用软件延时吧&#xff0c;总是由于时隙不精确&#xff0c;通信不稳定。按说不稳定情况也不频繁&#xff0c;但考虑到未来需要对上百、上千米外的单总线设备通信&#xff0c;开发的时候偷个懒&#xff0c;到应用…

Go新项目-为何选Gin框架?(0)

先说结论&#xff1a;我们选型Gin框架 早在大概在2019年下旬&#xff0c;由于内部一个多线程上传的需求&#xff0c;考虑到Go协程的优势&#xff1b; 内部采用Gin框架编写了内部的数据上传平台BAP&#xff0c;采用GinVue开发&#xff0c;但前期没考虑到工程化思维&#xff0c;导…

【数据结构】栈的远房亲戚——队列

队列的基本概念 前言一、队列的定义二、队列的重要术语三、队列的基本操作四、数据结构的三要素4.1 线性表的三要素4.2 栈的三要素4.3 队列的三要素 结语 前言 大家好&#xff0c;很高兴又和大家见面啦&#xff01;&#xff01;&#xff01; 在经过前面内容的介绍&#xff0c;…