pip install SQLAlchemy
import sqlalchemy
print(sqlalchemy.__version__)
from sqlalchemy import create_engine
engine = create_engine(
'mysql+pymysql://127.0.0.1:3306/wss_demmo?charset=utf8&user=root&password=123456',
echo=True, # 打印日志
future=True # 新版本接口格式
)
from sqlalchemy import create_engine,text
with engine.connect() as conn:
result = conn.execute(text("select * from test"))
print(result.all())
with engine.begin() as conn:
result = conn.execute(text("SELECT * FROM TEST"));
for row in result:
print(f"id:{row.id},name:{row.name}")
默认返回的是元组类型,可以通过索引和属性名称来获取每一组的数据
使用result.mappings()
修饰符转换为MapingResult
对象,这样一来集合的成员类型都是字典类型。
with engine.begin() as conn:
result = conn.execute(text("SELECT * FROM TEST"));
for row in result.mappings():
print(row) # {'id': '8', 'name': '赵六'}
with engine.begin() as conn:
result = conn.execute(text("SELECT * FROM TEST WHERE id > :id"),{"id":5});
print(result.all())
参数使用:参数名
来指定,并在后面的字典参数中来进行传值。如 :id与后面的字典就是对应关系。
当需要传递多组参数,执行多次语句时,可以传递字典列表来实现,如下面的保存示例。
默认事务在执行以后会自动回滚,如果需要提交数据,需要调用conn.commit();
with engine.connect() as conn:
result = conn.execute(text("INSERT INTO test (id, name) VALUES (:id, :name)"),
[{"id": 5, "name": "赵六"}, {"id": 6, "name": "张七"}]);
conn.commit()
还有另一种提交方法,使用begin来获取连接,这种会在事务结束时自动提交
with engine.begin() as conn:
result = conn.execute(text("INSERT INTO test (id, name) VALUES (:id, :name)"),
[{"id": 8, "name": "赵六"}, {"id": 7, "name": "张七"}]);
from sqlalchemy.orm import Session
stmt = text("SELECT * FROM TEST WHERE id > :id").bindparams(id=3)
with Session(engine) as session:
result = session.execute(stmt);
print(result.all())
同connection一样,进行插入和修改操作时需要提交(session.commit())才可以生效。
with Session(engine) as session:
result = session.execute(text("UPDATE TEST SET name=:name where id=:id"), [{"name": "展招", "id": 5}, {"name": "包大人", "id": 6}]);
session.commit()
创建元数据对象
from sqlalchemy import MetaData
metadata_obj = MetaData()
from sqlalchemy import Table, Column, Integer, String
user_table = Table(
"user_account",
metadata_obj,
Column('id', Integer, primary_key=True), # 主键约束
Column('name', String(30)),
Column('fullname', String(50))
)
from sqlalchemy import ForeignKey
address_table = Table(
"address",
metadata_obj,
Column('id', Integer, primary_key=True), # 主键约束
Column('user_id', ForeignKey('user_account.id'), nullable=False), # ForeignKey:外键约束 nullable:非空约束
Column('email_address', String(100), nullable=False)
)
在列
定义中使用ForeignKey
对象时,我们可以省略该列
的数据类型 ;它是从相关列的自动推断出来的,在上面的示例中,列的Integer
数据类型。user_account.id
查看表对象的主键约束
print(user_table.primary_key)
元数据对象通过已经关联的table对象生成数据库表。
metadata_obj.create_all(engine)
MetaData
对象还具有一个MetaData.drop_all()
方法,该方法将删除所有元数据对象关联的数据库表。
通过注册获取元数据基类
from sqlalchemy.orm import registry
mapper_registry = registry()
Base = mapper_registry.generate_base()
还提供了一个方法可以直接获取到基类
from sqlalchemy.orm import declarative_base
Base = declarative_base()
现在就可以根据基类来映射类了
from datetime import datetime
import pymysql
from sqlalchemy import create_engine
from sqlalchemy.orm import declarative_base
from sqlalchemy import Column, Integer, String, DateTime, Enum, SmallInteger, Boolean
from enum import IntEnum
from sqlalchemy.dialects.mysql import TINYINT, CHAR
class SexEnum(IntEnum):
MAN = 1
WOMAN = 0
class Student(Base):
__tablename__ = "student"
id = Column(type_=Integer, primary_key=True, name="id", autoincrement=True)
stu_no = Column(type_=Integer, nullable=False, comment="学号", doc="只在代码中能看到的注释", unique=True)
stu_name = Column(CHAR(16), nullable=False, comment="姓名", default="默认值")
sex = Column(Enum(SexEnum), default=None, comment="性别")
age = Column(TINYINT(unsigned=True), default=0, comment="年龄")
create_at = Column(type_=DateTime, default=datetime.now())
is_vaild = Column(Boolean, default=True)
创建数据表
# 通过注册获取的元数据来创建表
mapper_registry.metadata.create_all(engine)
# 通过基类的元数据创建表
Base.metadata.create_all(engine)
通过表信息逆向生成Table对象,不需要创建具体的实体对象。Table对象的使用方法和上面的一样。
address = Table("address", metadata_obj, autoload_with=engine)
from sqlalchemy.orm import declarative_base, relationship
from sqlalchemy import Column, Integer, String, DateTime, Enum, SmallInteger, Boolean, ForeignKey
class Address:
__tablename__ = "address"
stu_id = Column(Integer, ForeignKey(Student.id)) # 外键
user = relationship("User", backref="address") # 一对多
user = relationship("User", backref="address",uselist=False) # 一对一
from sqlalchemy.orm import Session
session = Session(bind=engine, future=True)
执行的sql都需要使用session的execute方法或者engine.connect()来执行,如果对数据进行了操作,还需要commit才可以生效。
使用Insert.values()
from sqlalchemy.orm import Session
from sqlalchemy import insert
session = Session(bind=engine, future=True)
stmt = insert(User).values(name='spongebob', fullname="Spongebob Squarepants")
with session:
session.execute(stmt)
session.commit()
使用compile()方法可以获取到执行sql的相关信息
compiled = stmt.compile()
print(compiled)#INSERT INTO user_account (name, fullname) VALUES (:name, :fullname)
print(compiled.params#{'name': 'spongebob', 'fullname': 'Spongebob Squarepants'}
如果需要获取插入后生成的主键,可以这样获取
result = session.execute(stmt)
session.commit()
print(result.inserted_primary_key)#(3,)
返回元组,因为主键可能包含多个列。这称为复合主键。
使用session.add()
from sqlalchemy.orm import Session
session = Session(bind=engine, future=True)
print("连接")
with session:
stu = Student(id=3, stu_no=3, stu_name="李四", sex=SexEnum.MAN)
Address(user=stu)
session.add(stu)
session.commit()
with engine.connect() as conn:
result = conn.execute(
insert(User),
[
{"name": "sandy", "fullname": "Sandy Cheeks"},
{"name": "patrick", "fullname": "Patrick Star"}
]
)
conn.commit()
print("连接")
with session:
stu_list = []
addrs = []
for i in range(10):
stu = Student(stu_no=i, stu_name="李四", sex=SexEnum.MAN)
addrs.append(Address(user=stu))
stu_list.append(stu)
session.add_all(addrs)
session.add_all(stu_list)
session.commit()
select_stmt = select(User.id,User.name+"的地址")
insert_stmt = insert(Address).from_select(
["user_id", "email_address"], select_stmt
)
print(insert_stmt)
mysql数据库好像不行,可以在其他数据库上试试;
UPDATE 和 DELETE 语句也支持 RETURNING 功能
insert_stmt = insert(address_table).returning(address_table.c.id, address_table.c.email_address)
print(insert_stmt)
#INSERT INTO address (id, user_id, email_address)
#VALUES (:id, :user_id, :email_address)
#RETURNING address.id, address.email_address
也可以在insert_statement中结合使用
print(insert_stmt.returning(address_table.c.id, address_table.c.email_address))
session.get(Entity,key);
stmt = select(Student.id,Student.sex)
rows = session.execute(stmt).fetchall()
for row in rows:
print(row)
条件查询
stmt = select(User).where(User.name == '张三')
print(stmt) #SELECT user_account.id, user_account.name, user_account.fullname
#FROM user_account
#WHERE user_account.name = :name_1
with engine.connect() as conn:
result = conn.execute(stmt)
for row in result:
print(row)