SQLAlchemy 学习(一)

本文介绍如何使用Python ORM框架SQLAlchemy连接数据库并执行基本操作。涵盖安装配置、引擎创建、元数据管理、表定义及约束等内容。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >


转载自:http://snoopyxdy.blog.163.com/blog/static/6011744020147623443840/


最近用到比较多的Python,当然访问数据库不能用原生的模块直接写Sql语句,这样太累。找了一本SQLAlchemy的教材来研究,记下学习笔记把。

相关的代码的例子在:

一、安装:
先安装pip工具,然后设置好源服务器,用豆瓣的比较好,国外的源被墙了。

pip install  MySQL - python
pip install  SQLAlchemy

二、Engine 数据库引擎
想要连接使用SQLAlchemy连接数据库,必须先创建一个引擎来连接,下面是创建引擎的相关代码:
   
# -*- coding: utf-8 -*-
from sqlalchemy import *
__engine = create_engine('mysql://root:@192.168.150.3/test',convert_unicode=True, echo=True)
#conn 是DB-API连接对象
conn = __engine.connect()
#result是数据库游标
result = conn.execute('select * from tf_user')
for row in result:
    print row
conn.close()

create_engine 类接受的参数如下:
1、connect_args 数据库链接参数,一般使用中文需要传递

{'charset':'utf8'}

2、convert_unicode 将保存的unicode字符串数据转为2进制存入数据库,取出时也将2进制取出专程unicode,主要用于数据库不支持Unicode编码使用,默认 False
3、creator 一个可以被调用的对象(带有__call__的对象),返回DB-API的链接对象,默认None
4、echo 是否输出SQLAlchemy日志,包括拼接的sql语句,默认None
5、 echo_pool 是否输出连接池日志,从连接池取出或放入,默认None
6、 encoding 设置传输数据的编码,默认是False
7、module 设置使用这个数据库哪一个连接模块,比如某些数据库安装了几个连接模块,默认False
8、pool 如果设定,则使用一个已经存在的连接池,不设定表示重新创建一个,默认None
9、 poolclass 表示这个引擎是否自己实现连接池类,否则会使用 sqlalchemy.pool.QueuePool ,而SQLite会使用 sqlalchemy.pool.SingletonThreadPool, 默认 None
10、 max_overflow 表示连接池允许超出的连接数,默认是10
11、pool_size 表示连接池数量,默认是5
12、pool_recycle 单位秒,表示将闲置的连接释放掉,对于mysql数据库会自动释放闲置连接,有必要对这个值进行设置
13、pool_timeout 从连接池中获取连接的超时时间,单位秒,默认是30
14、strategy 为这个连接引擎选择一个别用的策略,当前备用策略包括"threadlocal"和"plain"
15、"threadlocal" 在一个线程中重用一个连接,执行多条语句
16、"plain" (默认) 对每一条语句使用一个连接
17、 threaded 仅在Oracle数据库使用,默认False
18、 use_ansi 仅在Oracle数据库使用
19、 use_oids 仅在PostgreSQL数据库使用

此句返回的result是一个ResultProxy的实例

result = conn.execute('select * from tf_user')

具有如下的属性和方法:
1、__iter__() 可迭代
2、fetchone() 获取第一行数据,返回类型 RowProxy
3、fetchall() 获取所有的数据,返回类型  RowProxy 数组
4、scalar() ,获取第一列名的第一条数据,然后关闭游标
5、keys 属性,返回列明的数组
6、rowcount 属性,返回记录数
7、close() 关闭连接,将连接返回连接池
8、fetchmany(size=None),根据数量返回RowProxy类型数组

此句迭代的 row是 RowProxy实例,具有如下属性和方法:

for row in result :
    print row

RowProxy 类型
1、__getattr__() 可以通过 object.column_name 获取值
2、__getitem__() 可以通过 object[column_name] 或者 object[column_position] 获取值
3、keys() 提供所有 column_name 的数组
4、values() 提供所有 value 值的数组
5、items() 提供一个 元组(column_name,value)的数组

三、MetaData 类
MetaData主要用于保存表结构,连接字符串等数据,是一个多表共享的对象

metadata = MetaData () #生成一个未绑定数据源的metadata
bound_meta = MetaData('sqlite:///test2.db') #绑定了数据源的metadata

我们可以利用meatadata.bind来绑定上面生成的数据源引擎

metadata = MetaData ()
__engine = create_engine ( 'mysql://root:@192.168.150.3/test' , connect_args ={ 'charset' : 'UTF8' }, echo = True ,
                         encoding = 'UTF-8' )
metadata . bind = __engine #将metadata绑定数据源

执行create_all方法来创建表,这个操作是安全的操作,会先判断表是否存在

metadata.create_all()


四、Table类
构造函数:

Table.__init__(self, name, metadata,*args, **kwargs)

1、name 表名
2、metadata 共享的元数据
3、*args Column 是列定义,详见下一节
下面是可变参数 **kwargs 定义
4、schema 此表的结构名称,默认None
5、autoload 自动从现有表中读入表结构,默认False
6、autoload_with 从其他engine读取结构,默认None,例: 

db = create_engine ( 'sqlite:///devdata.sqlite' )
brand_table = Table ( 'brand' , metadata , autoload = True , autoload_with = db )

7、include_columns 如果autoload设置为True,则此项数组中的列明将被引用,没有写的列明将被忽略,None表示所有都列明都引用,默认None
8、mustexist 如果为True,表示这个表必须在其他的python应用中定义,必须是metadata的一部分,默认False
9、useexisting 如果为True,表示这个表必须被其他应用定义过,将忽略结构定义,默认False
10、owner 表所有者,用于Orcal,默认None
11、quote 设置为True,如果表明是SQL关键字,将强制转义,默认False
12、quote_schema  设置为True,如果列明是SQL关键字,将强制转义,默认False
13、mysql_engine  mysql专用,可以设置'InnoDB'或'MyISAM'

五、Column类
构造函数:

Column.__init__(self,  name,  type_,  *args,  **kwargs)

1、name 列名
2、type_ 类型,更多类型 sqlalchemy.types
3、*args Constraint(约束),  ForeignKey(外键),  ColumnDefault(默认), Sequenceobjects(序列)定义
4、key 列明的别名,默认None
下面是可变参数 **kwargs
5、primary_key 如果为True,则是主键
6、nullable 是否可为Null,默认是True
7、default 默认值,默认是None
8、index 是否是索引,默认是True
9、unique 是否唯一键,默认是False
10、onupdate 指定一个更新时候的值,这个操作是定义在SQLAlchemy中,不是在数据库里的,当更新一条数据时设置,大部分用于updateTime这类字段
11、autoincrement 设置为整型自动增长,只有没有默认值,并且是Integer类型,默认是True
12、quote 如果列明是关键字,则强制转义,默认False

一个简单的表定义代码:

user_table = Table (
    'tf_user2' , metadata ,
    Column ( 'id' , Integer , primary_key = True ),
    Column ( 'user_name' , Unicode ( 16 , collation = 'utf8_bin' ), unique = True , nullable = False ),
    Column ( 'email_address' , Unicode ( 255 , collation = 'utf8_bin' ), unique = True , nullable = False ),
    Column ( 'password' , Unicode ( 40 , collation = 'utf8_bin' ), nullable = False ),
    Column ( 'first_name' , Unicode ( 255 , collation = 'utf8_bin' ), default = u '发' ),
    Column ( 'last_name' , Unicode ( 255 , collation = 'utf8_bin' ), default = u '发' ),
    Column ( 'created' , DateTime , default = datetime . now )
)


六、约束定义:
可以同时在列或者表中进行定义,相关代码如下:

product_table = Table (
  'product' , metadata ,
  Column ( 'brand_id' , Integer , ForeignKey ( 'brand.id' ), primary_key = True ),
  Column ( 'sku' , Unicode ( 80 ), primary_key = True ))

或者

product_table = Table (
  'product' , metadata ,
  Column ( 'brand_id' , Integer , ForeignKey ( 'brand.id' )), Column ( 'sku' , Unicode ( 80 )),
  PrimaryKeyConstraint ( 'brand_id' , 'sku' , name = 'prikey' ))


七、外键的定义
ForeignKey类构造函数如下:

ForeignKey.__init__(  self,  col-umn,  constraint=None,  use_alter=False,  name=None,  onupdate=None,  ondelete=None)


八、唯一定义
Unique类,相关代码如下,当然也可以在列中定义,下面这种是复合唯一约束

product_table = Table (
'product' , metadata ,
Column ( 'id' , Integer , primary_key = True ),
Column ( 'brand_id' , Integer , ForeignKey ( 'brand.id' )),
Column ( 'sku' , Unicode ( 80 )),
UniqueConstraint ( 'brand_id' , 'sku' ))


九、检查约束
例子:

payment_table = Table (
  'payment' , metadata ,
  Column ( 'amount' , Numeric ( 10 , 2 ), CheckConstraint ( 'amount > 0' )))
  Column ( 'original' , Numeric ( 10 , 2 ), CheckConstraint ( 'original> 0' )),
  Column ( 'discounted' , Numeric ( 10 , 2 ),
  CheckConstraint ( 'discounted > 0' )),
  CheckConstraint ( 'discounted < original' , name = 'check_constraint_1' ))


十、index索引对象
可以在列中定义,一般用到索引对象有下面几种情况:
1、定义多列复合索引
2、对索引命名
3、独立的对表创建索引,一般用于已经存在的表,增加索引
 使用例子

 i = Index ( 'idx_name' , user_table . c . first_name ,
 user_table . c . last_name , unique = True )
 i . create ( bind = e )
<think>我们正在编写个关于SQLAlchemy的入门教程。根据引用内容,我们知道SQLAlchemy有两种使用方式:Core和ORM。ORM建立在Core之上,Core更底层,可以直接执行SQL语句。对于初学者,通常从ORM开始学习,因为它更符合面向对象编程的习惯。 我们将按照以下结构组织教程: 1. 安装SQLAlchemy 2. 连接数据库 3. 使用ORM定义模型 4. 创建数据库表 5. 基本CRUD操作(增删改查) 6. 简单查询 同时,我们参考了引用[1]和引用[2]的内容,强调SQLAlchemy是Python开发人员与数据库交互的重要工具,并介绍了两种使用方式的区别。 下面开始编写教程:</think>### SQLAlchemy 入门教程:Python 数据库交互的终极指南 SQLAlchemy 是 Python 最强大的数据库工具包,提供完整的 SQL 功能和 ORM(对象关系映射)能力,让开发者能用面向对象的方式操作数据库[^1]。本教程将带你从零开始掌握 SQLAlchemy 的核心功能。 #### 1️⃣ 安装与环境准备 ```bash # 安装 SQLAlchemy 和 MySQL 驱动 pip install sqlalchemy pymysql ``` #### 2️⃣ 两种使用模式 SQLAlchemy 提供两种使用方式: - **Core**:底层 SQL 抽象层,适合需要直接控制 SQL 的场景 - **ORM**:高级对象关系映射,类似 Django ORM[^2] ```python from sqlalchemy import create_engine # 创建数据库连接 (MySQL 示例) engine = create_engine('mysql+pymysql://user:password@localhost/mydb') ``` #### 3️⃣ ORM 基础操作 **定义数据模型** ```python from sqlalchemy.ext.declarative import declarative_base from sqlalchemy import Column, Integer, String, DateTime Base = declarative_base() class User(Base): __tablename__ = 'users' id = Column(Integer, primary_key=True) name = Column(String(50), nullable=False) email = Column(String(120), unique=True) created_at = Column(DateTime, default=datetime.now) ``` **创建数据库表** ```python # 创建所有定义的表 Base.metadata.create_all(engine) ``` **CRUD 操作** ```python from sqlalchemy.orm import sessionmaker # 创建会话 Session = sessionmaker(bind=engine) session = Session() # 创建记录 new_user = User(name='Alice', email='alice@example.com') session.add(new_user) session.commit() # 查询记录 user = session.query(User).filter_by(name='Alice').first() print(user.email) # 输出: alice@example.com # 更新记录 user.email = 'new_email@example.com' session.commit() # 删除记录 session.delete(user) session.commit() ``` #### 4️⃣ 高级查询技巧 ```python # 条件查询 users = session.query(User).filter(User.name.like('A%')).all() # 排序和分页 users = session.query(User).order_by(User.created_at.desc()).limit(10).offset(0) # 聚合查询 from sqlalchemy import func count = session.query(func.count(User.id)).scalar() ``` #### 5️⃣ 表关系管理 ```python class Post(Base): __tablename__ = 'posts' id = Column(Integer, primary_key=True) title = Column(String(100)) user_id = Column(Integer, ForeignKey('users.id')) # 定义关系 author = relationship("User", back_populates="posts") # 在 User 类中添加反向引用 User.posts = relationship("Post", back_populates="author") # 查询用户的所有文章 user = session.query(User).get(1) for post in user.posts: print(post.title) ``` #### 6️⃣ 核心 SQL 操作 ```python from sqlalchemy import text # 直接执行 SQL result = engine.execute(text("SELECT * FROM users WHERE name = :name"), {'name': 'Alice'}) for row in result: print(row) ``` #### 7️⃣ 最佳实践 1. **连接池管理**:默认使用 QueuePool 连接池 2. **事务处理**:使用上下文管理器确保安全 ```python with session.begin(): session.add(User(name='Bob')) session.add(Post(title='First Post', user_id=1)) ``` 3. **性能优化**:使用 `selectinload` 避免 N+1 查询问题 ```python from sqlalchemy.orm import selectinload # 次性加载所有关联数据 users = session.query(User).options(selectinload(User.posts)).all() ``` ### 学习资源推荐 - 官方文档:https://www.sqlalchemy.org/ - SQLAlchemy ORM 教程:https://docs.sqlalchemy.org/en/14/orm/tutorial.html - SQLAlchemy Core 教程:https://docs.sqlalchemy.org/en/14/core/tutorial.html
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值