📜  Python数据持久性-SQLAlchemy

📅  最后修改于: 2020-11-07 08:27:49             🧑  作者: Mango


任何关系数据库都将数据保存在表中。表结构定义属性的数据类型,这些属性基本上仅是主要数据类型,这些属性被映射到Python的相应内置数据类型。但是,Python的用户定义对象无法持久存储和从SQL表检索。

这是SQL类型与面向对象的编程语言(例如Python)之间的差异。 SQL没有其他类似的数据类型,例如dict,tuple,list或任何用户定义的类。

如果必须将对象存储在关系数据库中,则在执行INSERT查询之前,应先将其实例属性解构为SQL数据类型。另一方面,从SQL表检索的数据属于主要类型。必须使用来构造所需类型的Python对象,以供在Python脚本中使用。这是对象关系映射器有用的地方。

对象关系映射器(ORM)

对象关系映射器(ORM)是类和SQL表之间的接口。 Python类映射到数据库中的某个表,因此可以自动执行对象和SQL类型之间的转换。

用Python代码编写的Student类映射到数据库中的Students表。结果,所有CRUD操作都通过调用该类的相应方法来完成。这样就无需在Python脚本中执行硬编码的SQL查询。

因此,ORM库充当原始SQL查询上的抽象层,并有助于快速的应用程序开发。 SQLAlchemy是Python流行的对象关系映射器。模型对象状态的任何操作都将与其在数据库表中的相关行同步。

SQLALchemy库包含ORM API和SQL表达式语言( SQLAlchemy Core )。表达式语言直接执行关系数据库的原始构造。

ORM是在SQL表达式语言之上构建的一种高级抽象用法模式。可以说,ORM是表达式语言的一种应用用法。在本主题中,我们将讨论SQLAlchemy ORM API并使用SQLite数据库。

SQLAlchemy使用方言系统通过各自的DBAPI实现与各种类型的数据库进行通信。所有方言都要求安装适当的DBAPI驱动程序。包括以下数据库类型的方言-

  • 火鸟
  • Microsoft SQL服务器
  • 的MySQL
  • 甲骨文
  • PostgreSQL的
  • SQLite的
  • Sybase公司

奥姆

使用pip实用工具可以轻松而直接地安装SQLAlchemy。

pip install sqlalchemy

要检查SQLalchemy是否已正确安装及其版本,请在Python提示符下输入以下内容-

>>> import sqlalchemy
>>>sqlalchemy.__version__
'1.3.11'

与数据库的交互是通过作为create_engine()函数的返回值获得的Engine对象完成的。

engine =create_engine('sqlite:///mydb.sqlite')

SQLite允许创建内存数据库。如下创建用于内存数据库的SQLAlchemy引擎-

from sqlalchemy import create_engine
engine=create_engine('sqlite:///:memory:')

如果您打算使用MySQL数据库,请使用其DB-API模块-pymysql和相应的方言驱动程序。

engine = create_engine('mysql+pymydsql://root@localhost/mydb')

create_engine有一个可选的echo参数。如果设置为true,则引擎生成的SQL查询将在终端上回显。

SQLAlchemy包含声明性基类。它充当模型类和映射表的目录。

from sqlalchemy.ext.declarative import declarative_base
base=declarative_base()

下一步是定义模型类。它必须从上述declarative_base类的base –对象派生。

将__ tablename __属性设置为要在数据库中创建的表的名称。其他属性对应于字段。每个对象都是SQLAlchemy中的Column对象,其数据类型来自以下列表之一-

  • 大整数
  • 布尔型
  • 日期
  • 约会时间
  • 浮动
  • 整数
  • 数字
  • 小整数
  • 文本
  • 时间

以下代码是名为Student的模型类,该模型类映射到Students表。

#myclasses.py
from sqlalchemy.ext.declarative import declarative_base
from sqlalchemy import Column, Integer, String, Numeric
base=declarative_base()
class Student(base):
   __tablename__='Students'
   StudentID=Column(Integer, primary_key=True)
   name=Column(String)
   age=Column(Integer)
   marks=Column(Numeric) 

要创建具有相应结构的Student表,请执行为基类定义的create_all()方法。

base.metadata.create_all(engine)

现在,我们必须声明一个Student类的对象。所有数据库事务(例如,从数据库中添加,删除或检索数据等)均由Session对象处理。

from sqlalchemy.orm import sessionmaker
Session = sessionmaker(bind=engine)
sessionobj = Session()

通过会话的add()方法将存储在Student对象中的数据物理添加到基础表中。

s1 = Student(name='Juhi', age=25, marks=200)
sessionobj.add(s1)
sessionobj.commit()

这是在学生表中添加记录的完整代码。执行后,相应的SQL语句日志将显示在控制台上。

from sqlalchemy import Column, Integer, String
from sqlalchemy import create_engine
from myclasses import Student, base
engine = create_engine('sqlite:///college.db', echo=True)
base.metadata.create_all(engine)

from sqlalchemy.orm import sessionmaker
Session = sessionmaker(bind=engine)
sessionobj = Session()
s1 = Student(name='Juhi', age=25, marks=200)
sessionobj.add(s1)
sessionobj.commit()

控制台输出

CREATE TABLE "Students" (
   "StudentID" INTEGER NOT NULL,
   name VARCHAR,
   age INTEGER,
   marks NUMERIC,
   PRIMARY KEY ("StudentID")
)
INFO sqlalchemy.engine.base.Engine ()
INFO sqlalchemy.engine.base.Engine COMMIT
INFO sqlalchemy.engine.base.Engine BEGIN (implicit)
INFO sqlalchemy.engine.base.Engine INSERT INTO "Students" (name, age, marks) VALUES (?, ?, ?)
INFO sqlalchemy.engine.base.Engine ('Juhi', 25, 200.0)
INFO sqlalchemy.engine.base.Engine COMMIT

会话对象还提供add_all()方法,以便在单个事务中插入多个对象。

sessionobj.add_all([s2,s3,s4,s5])
sessionobj.commit()

现在,记录已添加到表中,我们希望像SELECT查询一样从表中获取记录。会话对象具有query()方法来执行任务。查询对象由我们的Student模型上的query()方法返回。

qry=seesionobj.query(Student)

使用此Query对象的get()方法可获取与给定主键相对应的对象。

S1=qry.get(1)

当执行此语句时,其在控制台上回显的相应SQL语句将如下所示-

BEGIN (implicit)
SELECT "Students"."StudentID" AS "Students_StudentID", "Students".name AS 
   "Students_name", "Students".age AS "Students_age", 
   "Students".marks AS "Students_marks"
FROM "Students"
WHERE "Products"."Students" = ?
sqlalchemy.engine.base.Engine (1,)

query.all()方法返回可以使用循环遍历的所有对象的列表。

from sqlalchemy import Column, Integer, String, Numeric
from sqlalchemy import create_engine
from myclasses import Student,base
engine = create_engine('sqlite:///college.db', echo=True)
base.metadata.create_all(engine)
from sqlalchemy.orm import sessionmaker
Session = sessionmaker(bind=engine)
sessionobj = Session()
qry=sessionobj.query(Students)
rows=qry.all()
for row in rows:
   print (row)

在映射表中更新记录非常容易。您要做的就是使用get()方法获取一条记录,为所需的属性分配一个新值,然后使用会话对象提交更改。下面我们将Juhi学生的分数更改为100。

S1=qry.get(1)
S1.marks=100
sessionobj.commit()

通过从会话中删除所需的对象,删除记录同样容易。

S1=qry.get(1)
Sessionobj.delete(S1)
sessionobj.commit()