Skip to content

DataType

SQLAlchemy 为数据库中最常见的数据类型进行了抽象,他们都使用 Python 类来表示,所有这些代表数据类型的类都派生自TypeEngine 基类。

SQLAlchemy 中的数据类型分为两种形式:

  1. CamelCase 类型: 他们是 TypeEngine 的直接子类,该类型在最大程度上对数据库的类型进行了抽象,这意味着他们是与数据库无关的。SQLAlchemy 支持的数据库都可以使用这种类型来定义。例如 String 对应了数据库后端的 VARCHAR 数据类型。还有像 Boolean 尽管并不是所有的数据库都支持该类型,即使支持他们后端的表现也会有区别,但是 SQLAlchemy 屏蔽了他们的区别我们直接就可以使用,并且能够正确处理 Python 到数据库后端类型的转换
  2. UPPERCASE 类型: 他们是特定 CamelCase 数据类型的子类。他们总是代表一个精确的类型,并且是不可移植的。比较典型的就是 PostgreSQL 的 JSONB、SQL Server 的 IMAGE 和 MYSQL 的 TINYTEXT

CamelCase

SQLAlchemy 为大多数常见的数据类型提供了抽象,他们使用驼峰表示所以被称为 CamelCase 类型,这些数据类型能够在所有支持的数据库中安全迁移:

Python
from sqlalchemy import MetaData
from sqlalchemy import Table, Column, Integer, String

metadata_obj = MetaData()

user = Table(
    "user",
    metadata_obj,
    Column("user_name", String, primary_key=True),
    Column("email_address", String(60)),
)

常见 CamelCase 类型

类型对象 说明
Integer 整数
SmallInteger 较小的整数
BigInteger 大整数
Float 浮点数
Double 双精度浮点数
Numeric 数值(非整数)
Boolean 布尔类型
Date 日期
Time 时间
DateTime 日期时间
Interval 时间间隔
LargeBinary 大型二进制类型
PickleType Python 序列化对象(特殊的二进制)
String 定长字符串,允许String(size)
Text 可变大小字符串
Unicode 可变长度的 Unicode 字符串
Enum 枚举
Uuid UUID

Tips

CamelCase 可以看作是通用的类型,他自动在 Python <=> 特定数据库 间交换数据而不需要用户关系内部的细节。同时他们在构建 CREATE TABLE 语句是会自动替换为后端的支持的数据类型,用户不需要关心其中的细节。

UPPERCASE

全大写的数据类型形式表示特定于某个后端,他们都位于 sqlalchemy.dialects.xxx 命名空间中:

类型名 描述
ARRAY PostgreSQL 中 ARRAY
BIGINT -
BINARY -
BLOB -
BOOLEAN -
CHAR -
CLOB -
DATE -
DATETIME -
DECIMAL -
DOUBLE -
DOUBLE_PRECISION -
FLOAT -
INT -
INTEGER -
JSON -
NCHAR -
NUMERIC -
NVARCHAR -
REAL -
SMALLINT -
TEXT -
TIME -
TIMESTAMP -
UUID -
VBABINARY -
VARCHAR -

UPPERCASE 最大的特点就是在 CREATE TABLE 不会转换这些类型,他们原封不动的将他们传递给后端。因此如果后端不支持会导致错误。

对于每一个支持的后端都可以从 sqlalchemy.dialects.[database] 中获取所有该数据库支持的 UPPERCASE 类型。

为特定后端使用 UPPERCASE 类型

如果想要编写移植更好的程序,通常的建议一定是使用 CamelCase 类型。不过 SQLAlchemy 提供了一个 TypeEngine.with_variant() 方法来让 CamelCase 和 UPPERCASE 共同起作用:

Python
from sqlalchemy import MetaData
from sqlalchemy import Table, Column, Integer, String
from sqlalchemy.dialects.mysql import VARCHAR

metadata_obj = MetaData()

user = Table(
    "user",
    metadata_obj,
    Column("user_name", String(100), primary_key=True),
    # 在所有后端使用 String
    # 在 mysql 和 mariadb 上他使用字符集 utf8 的 VARCHAR(255)
    # TypeEngine.with_variant(type:TypeEngine, *dialect_names)
    # dialects 就是 url 前面的协议字符串
    Column(
        "bio",
        String(255).with_variant(VARCHAR(255, charset="utf8"), "mysql", "mariadb"),
    ),
)