SQLachemy基础

SQLAchemy

SQLAchemy是python编程语言下的一款ORM框架,该框架建立在数据库API之上,使用关系对象映射进行数据库操作,

简言之便是:将对象转换成SQL,然后使用数据API执行SQL并获取执行结果。

ORM框架的作用就是把数据库表的一行记录与一个对象互相做自动转换。 正确使用ORM的前提是了解关系数据库的原理。 ORM就是把数据库表的行与相应的对象建立关联,互相转换。 由于关系数据库的多个表还可以用外键实现一对多、多对多等关联,相应地, ORM框架也可以提供两个对象之间的一对多、多对多等功能。

安装:

1
pip3 install SQLALchemy

 数据库:

在这些URL 中,hostname 表示MySQL 服务所在的主机,可以是本地主机(localhost),
也可以是远程服务器。数据库服务器上可以托管多个数据库,因此database 表示要使用的
数据库名。如果数据库需要进行认证,username 和password 表示数据库用户密令

程序使用的数据库URL 必须保存到Flask 配置对象的SQLALCHEMY_DATABASE_URI 键中。配
置对象中还有一个很有用的选项,即SQLALCHEMY_COMMIT_ON_TEARDOWN 键,将其设为True
时,每次请求结束后都会自动提交数据库中的变动

1
2
3
4
5
6
7
8
9
from flask.ext.sqlalchemy import SQLAlchemy
basedir = os.path.abspath(os.path.dirname(__file__))
app = Flask(__name__)
app.config['SQLALCHEMY_DATABASE_URI'] =\
'sqlite:///' + os.path.join(basedir, 'data.sqlite')
app.config['SQLALCHEMY_COMMIT_ON_TEARDOWN'] = True
db = SQLAlchemy(app)
# db 对象是SQLAlchemy 类的实例,表示程序使用的数据库,同时还获得了Flask-SQLAlchemy
提供的所有功能。

复制代码
class Role(db.Model):
__tablename__ = 'roles'
id = db.Column(db.Integer, primary_key=True)
name = db.Column(db.String(64), unique=True)
def __repr__(self):
return '<Role %r>' % self.name
class User(db.Model):
__tablename__ = 'users'
id = db.Column(db.Integer, primary_key=True)
username = db.Column(db.String(64), unique=True, index=True)
def __repr__(self):
return '<User %r>' % self.username
示例
复制代码

一、内部处理

使用 Engine/ConnectionPooling/Dialect 进行数据库操作,Engine使用ConnectionPooling连接数据库,然后再通过Dialect执行SQL语句。

查询 删除和插入类似 都需要先实例一个 sqlalchemy.sql.dml 对象

create_engine() 会返回一个数据库引擎,echo 参数为 True 时,会显示每条执行的 SQL 语句,生产环境下可关闭。
sessionmaker() 会生成一个数据库会话类。这个类的实例可以当成一个数据库连接,它同时还记录了一些查询的数据,并决定什么时候执行 SQL 语句。由于 SQLAlchemy 自己维护了一个数据库连接池(默认 5 个连接)

 二、ORM功能使用

使用 ORM/Schema Type/SQL Expression Language/Engine/ConnectionPooling/Dialect 所有组件对数据进行操作。

根据类创建对象,对象转换成SQL,执行SQL。

  1、创建表

  2、操作表

1
2
3
4
5
6
7
obj = Users(name='alex1', exeven='sd')
session.add(obj)
session.add_all([
    Users(name='alex2', exeven='sd'),
    Users(name='alex3', exeven='sd'),
])
session.commit()

1
2
session.query(users.id).filter(Users.id > 2).delete()
session.commit()  

1
2
3
4
5
session.query(Users).filter(Users.id > 2).update({"name" : "999"})
session.query(Users).filter(Users.id > 2).update({Users.name: Users.name + "099"},
synchronize_session=False)
session.query(Users).filter(Users.id > 2).update({"num": Users.num + 1}, synchronize_session="evaluate")
session.commit()

1
2
3
4
ret = session.query(Users).all()
ret = session.query(Users.name, Users.extra).all()
ret = session.query(Users).filter_by(name='alex').all()
ret = session.query(Users).filter_by(name='alex').first()

其他

其他2

三、单表与多表

常用的SQLAlchemy关系选项

1、一对多

除了一对多之外,还有几种其他的关系类型。一对一关系可以用前面介绍的一对多关系
表示,但调用db.relationship() 时要把uselist 设为False,把“多”变成“一”。多对
一关系也可使用一对多表示,对调两个表即可,或者把外键和db.relationship() 都放在
“多”这一侧。最复杂的关系类型是多对多,需要用到第三张表,这个表称为关系表

 关联查询(relationship)

2、多对多 

数据库事务:

数据库会话db.session和Flasksession 对象没有关系。数据库会话也称为事务。

数据库会话能保证数据库的一致性。提交操作使用原子方式把会话中的对象全部写入数据库。

如果在写入会话的过程中发生了错误,整个会话都会失效。如果你始终把相关改动放
在会话中提交,就能避免因部分更新导致的数据库不一致性。
数据库会话也可回滚。调用db.session.rollback() 后,添加到数据库会话中的所有对象都会还原到它们在数据库时的状态。

 补充

如何查看查询生成的原生SQL:

1
2
3
>>> str(User.query.filter_by(role=user_role))
'SELECT users.id AS users_id, users.username AS users_username,
users.role_id AS users_role_id FROM users WHERE :param_1 = users.role_id'

如何批量插入大批数据?
可以使用非 ORM 的方式:

1
2
3
4
5
session.execute(
    User.__table__.insert(),
    [{'name': `randint(1, 100)`,'age': randint(1, 100)} for i in xrange(10000)]
)
session.commit()

 如何让执行的 SQL 语句增加前缀?
使用 query 对象的 prefix_with() 方法:

1
2
session.query(User.name).prefix_with('HIGH_PRIORITY').all()
session.execute(User.__table__.insert().prefix_with('IGNORE'), {'id': 1, 'name': '1'})

 如何替换一个已有主键的记录?
使用 session.merge() 方法替代 session.add(),其实就是 SELECT + UPDATE:

1
2
3
user = User(id=1, name='ooxx')
session.merge(user)
session.commit()

 如何使用无符号整数?
可以使用 MySQL:

1
2
from sqlalchemy.dialects.mysql import INTEGER
id = Column(INTEGER(unsigned=True), primary_key=True)

 如何指定使用 InnoDB,以及使用 UTF-8 编码?
最简单的方式就是修改数据库的默认配置。如果非要在代码里指定的话,可以这样:

1
2
3
4
5
class User(BaseModel):
    __table_args__ = {
        'mysql_engine': 'InnoDB',
        'mysql_charset': 'utf8'
    }

 如何设置外键约束?

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
from random import randint
from sqlalchemy import ForeignKey
 
 
class User(BaseModel):
    __tablename__ = 'user'
 
    id = Column(Integer, primary_key=True)
    age = Column(Integer)
 
 
class Friendship(BaseModel):
    __tablename__ = 'friendship'
 
    id = Column(Integer, primary_key=True)
    user_id1 = Column(Integer, ForeignKey('user.id'))
    user_id2 = Column(Integer, ForeignKey('user.id'))

更新之后拿到更新数据的ID

1
2
3
4
5
6
7
8
def test_sqlachemy_select():
    obj = db.session.query(VMWareEnvModel).filter_by(name='changename')
    # <class 'sqlalchemy.orm.query.Query'>
    # .first后 <class 'app.scheduler.rhev.env.models.VMWareEnvModel'>
    obj.update({VMWareEnvModel.user: "SQLTEST", VMWareEnvModel.password: "abc123456"})
    db.session.commit()
    obj_id = obj.first().id
    print obj_id

 为什么无法删除 in 操作查询出来的记录?

1
session.query(User).filter(User.id.in_((1, 2, 3))).delete()

 抛出这样的异常:

sqlalchemy.exc.InvalidRequestError: Could not evaluate current criteria in Python.  Specify 'fetch' or False for the synchronize_session parameter.

但这样是没问题的:

1
session.query(User).filter(or_(User.id == 1, User.id == 2, User.id == 3)).delete()

 

参考:https://www.keakon.net/2012/12/03/SQLAlchemy%E4%BD%BF%E7%94%A8%E7%BB%8F%E9%AA%8C

参考:https://www.cnblogs.com/kongqi816-boke/p/5752510.html

posted @   总要做些什么  阅读(628)  评论(0编辑  收藏  举报
编辑推荐:
· .NET Core 中如何实现缓存的预热?
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
· 基于Microsoft.Extensions.AI核心库实现RAG应用
· Linux系列:如何用heaptrack跟踪.NET程序的非托管内存泄露
阅读排行:
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· .NET Core 中如何实现缓存的预热?
· 阿里巴巴 QwQ-32B真的超越了 DeepSeek R-1吗?
· 如何调用 DeepSeek 的自然语言处理 API 接口并集成到在线客服系统
· 【译】Visual Studio 中新的强大生产力特性
点击右上角即可分享
微信分享提示