SQLAlchemy 2.0 文档
方言
- PostgreSQL
- MySQL 和 MariaDB
- SQLite
- Oracle
- Microsoft SQL Server¶
- 对 Microsoft SQL Server 数据库的支持。
- 外部方言
- 自动递增行为 / IDENTITY 列
- SEQUENCE 支持
- VARCHAR / NVARCHAR 上的 MAX
- 排序规则支持
- LIMIT/OFFSET 支持
- DDL 注释支持
- 事务隔离级别
- 临时表 / 连接池的资源重置
- 可空性
- 日期/时间处理
- 大型文本/二进制类型弃用
- 多部分模式名称
- 传统模式
- 聚簇索引支持
- 列存储索引支持
- MSSQL 特定索引选项
- 兼容性级别
- 触发器
- 行计数支持 / ORM 版本控制
- 启用快照隔离
- SQL Server SQL 结构
- SQL Server 数据类型
- PyODBC
- pymssql
- aioodbc
项目版本
- 上一章: Oracle
- 下一章: 常见问题解答
- 上一级: 首页
- 本页内容
- Microsoft SQL Server
- 对 Microsoft SQL Server 数据库的支持。
- 外部方言
- 自动递增行为 / IDENTITY 列
- SEQUENCE 支持
- VARCHAR / NVARCHAR 上的 MAX
- 排序规则支持
- LIMIT/OFFSET 支持
- DDL 注释支持
- 事务隔离级别
- 临时表 / 连接池的资源重置
- 可空性
- 日期/时间处理
- 大型文本/二进制类型弃用
- 多部分模式名称
- 传统模式
- 聚簇索引支持
- 列存储索引支持
- MSSQL 特定索引选项
- 兼容性级别
- 触发器
- 行计数支持 / ORM 版本控制
- 启用快照隔离
- SQL Server SQL 结构
- SQL Server 数据类型
- PyODBC
- pymssql
- aioodbc
Microsoft SQL Server¶
对 Microsoft SQL Server 数据库的支持。
下表总结了当前对数据库发布版本的支持级别。
支持类型 |
版本 |
---|---|
2012+ |
|
2005+ |
DBAPI 支持¶
以下方言/DBAPI 选项可用。请参阅各个 DBAPI 部分以获取连接信息。
外部方言¶
除了具有原生 SQLAlchemy 支持的上述 DBAPI 层外,还有用于其他与 SQL Server 兼容的 DBAPI 层的第三方方言。请参阅 方言 页面上的“外部方言”列表。
自动递增行为 / IDENTITY 列¶
SQL Server 使用所谓的“自动递增”行为 IDENTITY
结构,该结构可以放置在表中的任何单个整数列上。SQLAlchemy 在其对整数主键列的默认“自动递增”行为中考虑 IDENTITY
,如 Column.autoincrement
中所述。这意味着在默认情况下,Table
中的第一个整数主键列将被视为标识列 - 除非它与 Sequence
相关联 - 并且将生成相应的 DDL
from sqlalchemy import Table, MetaData, Column, Integer
m = MetaData()
t = Table('t', m,
Column('id', Integer, primary_key=True),
Column('x', Integer))
m.create_all(engine)
上面的示例将生成以下 DDL:
CREATE TABLE t (
id INTEGER NOT NULL IDENTITY,
x INTEGER NULL,
PRIMARY KEY (id)
)
如果不需要生成默认的 IDENTITY
,请在第一个整数主键列上为 Column.autoincrement
标志指定 False
m = MetaData()
t = Table('t', m,
Column('id', Integer, primary_key=True, autoincrement=False),
Column('x', Integer))
m.create_all(engine)
要将 IDENTITY
关键字添加到非主键列,请在所需的 Column
对象上为 Column.autoincrement
标志指定 True
,并确保在任何整数主键列上将 Column.autoincrement
设置为 False
m = MetaData()
t = Table('t', m,
Column('id', Integer, primary_key=True, autoincrement=False),
Column('x', Integer, autoincrement=True))
m.create_all(engine)
在版本 1.4 中弃用: Column
的 mssql_identity_start
和 mssql_identity_increment
参数已弃用,应该用 Identity
对象替换。同时指定两种配置 IDENTITY 的方法会导致编译错误。这些选项也不再作为 Inspector.get_columns()
中的 dialect_options
键的一部分返回。请使用 identity
键中的信息。
在版本 1.3 中弃用: 使用 Sequence
来指定 IDENTITY 特性已弃用,将在未来的版本中删除。请使用 Identity
对象参数 Identity.start
和 Identity.increment
。
注意
表中只能有一个 IDENTITY 列。当使用 autoincrement=True
启用 IDENTITY 关键字时,SQLAlchemy 不会阻止多个列同时指定该选项。相反,SQL Server 数据库将拒绝 CREATE TABLE
语句。
注意
尝试为标记为 IDENTITY 的列提供值的 INSERT 语句将被 SQL Server 拒绝。为了使该值被接受,必须启用会话级选项“SET IDENTITY_INSERT”。当使用核心 Insert
结构时,SQLAlchemy SQL Server 方言将在执行此操作时自动执行此操作;如果执行为 IDENTITY 列指定了一个值,那么“IDENTITY_INSERT”选项将在该语句调用的范围内被启用。但是,这种情况的性能不高,不应该在正常使用中依赖它。如果表在其实数主键列中实际上不需要 IDENTITY 行为,则在创建表时应禁用该关键字,确保设置 autoincrement=False
。
控制“开始”和“增量”¶
使用传递给Identity
对象的Identity.start
和Identity.increment
参数,可以对IDENTITY
生成器的“开始”和“增量”值进行特定控制。
from sqlalchemy import Table, Integer, Column, Identity
test = Table(
'test', metadata,
Column(
'id',
Integer,
primary_key=True,
Identity(start=100, increment=10)
),
Column('name', String(20))
)
上面Table
对象的CREATE TABLE将是
CREATE TABLE test (
id INTEGER NOT NULL IDENTITY(100,10) PRIMARY KEY,
name VARCHAR(20) NULL,
)
注意
Identity
对象除了start
和increment
之外,还支持许多其他参数。这些参数不受SQL Server支持,在生成CREATE TABLE ddl时将被忽略。
将IDENTITY与非整数数值类型一起使用¶
SQL Server还允许将IDENTITY
与NUMERIC
列一起使用。为了在SQLAlchemy中平滑地实现此模式,列的主数据类型应保持为Integer
,但是部署到SQL Server数据库的基础实现类型可以使用TypeEngine.with_variant()
指定为Numeric
from sqlalchemy import Column
from sqlalchemy import Integer
from sqlalchemy import Numeric
from sqlalchemy import String
from sqlalchemy.ext.declarative import declarative_base
Base = declarative_base()
class TestTable(Base):
__tablename__ = "test"
id = Column(
Integer().with_variant(Numeric(10, 0), "mssql"),
primary_key=True,
autoincrement=True,
)
name = Column(String)
在上面的示例中,Integer().with_variant()
提供了清晰的用法信息,准确地描述了代码的意图。autoincrement
仅适用于Integer
的一般限制是在元数据级别建立的,而不是在每个方言级别建立的。
当使用上述模式时,从插入行返回的主键标识符,也就是分配给如上面TestTable
之类的ORM对象的标识符,在使用SQL Server时将是Decimal()
的实例,而不是int
。将Numeric
类型的数值返回类型更改为返回浮点数,方法是将False传递给Numeric.asdecimal
。为了将上面Numeric(10, 0)
的返回类型规范化为返回Python整数(在Python 3中也支持“长”整数值),请使用TypeDecorator
,如下所示
from sqlalchemy import TypeDecorator
class NumericAsInteger(TypeDecorator):
'''normalize floating point return values into ints'''
impl = Numeric(10, 0, asdecimal=False)
cache_ok = True
def process_result_value(self, value, dialect):
if value is not None:
value = int(value)
return value
class TestTable(Base):
__tablename__ = "test"
id = Column(
Integer().with_variant(NumericAsInteger, "mssql"),
primary_key=True,
autoincrement=True,
)
name = Column(String)
INSERT行为¶
在INSERT时处理IDENTITY
列涉及两种关键技术。最常见的是能够为给定的IDENTITY
列获取“最后插入的值”,这是SQLAlchemy在许多情况下(最重要的是在ORM中)隐式执行的过程。
获取此值的过程有几个变体
在绝大多数情况下,RETURNING与SQL Server上的INSERT语句一起使用,以便获取新生成的键值
INSERT INTO t (x) OUTPUT inserted.id VALUES (?)
从SQLAlchemy 2.0开始,“Insert Many Values” Behavior for INSERT statements功能也默认用于优化多行INSERT语句;对于SQL Server,该功能适用于RETURNING和非RETURNING INSERT语句。
版本 2.0.10 中的变更: 由于SQL Server中行排序问题,SQLAlchemy版本2.0.9暂时禁用了“Insert Many Values” Behavior for INSERT statements功能。从2.0.10开始,该功能重新启用,对工作单元对RETURNING进行排序的要求进行了特殊情况处理。
当RETURNING不可用或已通过
implicit_returning=False
禁用时,使用scope_identity()
函数或@@identity
变量;行为因后端而异当使用PyODBC时,短语
; select scope_identity()
将附加到INSERT语句的末尾;将获取第二个结果集以接收该值。给定一张表,如下所示t = Table( 't', metadata, Column('id', Integer, primary_key=True), Column('x', Integer), implicit_returning=False )
INSERT将类似于
INSERT INTO t (x) VALUES (?); select scope_identity()
其他方言(如pymssql)将在INSERT语句之后调用
SELECT scope_identity() AS lastrowid
。如果将标志use_scope_identity=False
传递给create_engine()
,则改为使用语句SELECT @@identity AS lastrowid
。
包含IDENTITY
列的表将禁止显式引用标识列的INSERT语句。SQLAlchemy方言将在使用核心insert()
构造(不是纯字符串SQL)创建的INSERT构造引用标识列时检测到这一点,在这种情况下,将在插入语句继续之前发出SET IDENTITY_INSERT ON
,并在执行之后发出SET IDENTITY_INSERT OFF
。鉴于此示例
m = MetaData()
t = Table('t', m, Column('id', Integer, primary_key=True),
Column('x', Integer))
m.create_all(engine)
with engine.begin() as conn:
conn.execute(t.insert(), {'id': 1, 'x':1}, {'id':2, 'x':2})
上面的列将使用IDENTITY创建,但是我们发出的INSERT语句指定了显式值。在回显输出中,我们可以看到SQLAlchemy是如何处理这一点的
CREATE TABLE t (
id INTEGER NOT NULL IDENTITY(1,1),
x INTEGER NULL,
PRIMARY KEY (id)
)
COMMIT
SET IDENTITY_INSERT t ON
INSERT INTO t (id, x) VALUES (?, ?)
((1, 1), (2, 2))
SET IDENTITY_INSERT t OFF
COMMIT
这是一个适用于测试和批量插入场景的辅助用例。
SEQUENCE支持¶
Sequence
对象创建“真实”序列,即CREATE SEQUENCE
>>> from sqlalchemy import Sequence
>>> from sqlalchemy.schema import CreateSequence
>>> from sqlalchemy.dialects import mssql
>>> print(CreateSequence(Sequence("my_seq", start=1)).compile(dialect=mssql.dialect()))
CREATE SEQUENCE my_seq START WITH 1
对于整数主键生成,SQL Server的IDENTITY
构造通常应该优于序列。
提示
T-SQL的默认起始值为-2**63
,而不是大多数其他SQL数据库中的1。如果预期默认值为1,则用户应显式设置Sequence.start
。
seq = Sequence("my_sequence", start=1)
版本 1.4 中的新增内容: 添加了SQL Server对Sequence
的支持。
版本 2.0 中的变更: SQL Server方言将不再隐式地为CREATE SEQUENCE
呈现“START WITH 1”,这是版本1.4中首次实现的行为。
VARCHAR / NVARCHAR上的MAX¶
SQL Server 在 VARCHAR
和 NVARCHAR
数据类型中支持特殊字符串“MAX”,表示“可能的最大长度”。方言目前将此处理为基本类型中的长度为“None”,而不是提供这些类型的方言特定版本,以便指定的基本类型(例如 VARCHAR(None)
)可以在多个后端上假定“无长度”行为,而无需使用方言特定类型。
要构建具有 MAX 长度的 SQL Server VARCHAR 或 NVARCHAR,请使用 None
my_table = Table(
'my_table', metadata,
Column('my_data', VARCHAR(None)),
Column('my_n_data', NVARCHAR(None))
)
排序规则支持¶
字符排序规则由基本字符串类型支持,由字符串参数“collation”指定
from sqlalchemy import VARCHAR
Column('login', VARCHAR(32, collation='Latin1_General_CI_AS'))
当这样的列与 Table
关联时,此列的 CREATE TABLE 语句将生成
login VARCHAR(32) COLLATE Latin1_General_CI_AS NULL
LIMIT/OFFSET 支持¶
MSSQL 从 SQL Server 2012 开始通过“OFFSET n ROWS”和“FETCH NEXT n ROWS”子句添加了对 LIMIT / OFFSET 的支持。如果检测到 SQL Server 2012 或更高版本,SQLAlchemy 会自动支持这些语法。
在版本 1.4 中更改: 添加了对 SQL Server“OFFSET n ROWS”和“FETCH NEXT n ROWS”语法的支持。
对于仅指定 LIMIT 而没有 OFFSET 的语句,所有版本的 SQL Server 都支持 TOP 关键字。当没有 OFFSET 子句时,此语法用于所有 SQL Server 版本。例如,以下语句
select(some_table).limit(5)
将类似地呈现为
SELECT TOP 5 col1, col2.. FROM table
对于 SQL Server 2012 之前的 SQL Server 版本,使用 LIMIT 和 OFFSET 或仅使用 OFFSET 的语句将使用 ROW_NUMBER()
窗口函数呈现。例如,以下语句
select(some_table).order_by(some_table.c.col3).limit(5).offset(10)
将类似地呈现为
SELECT anon_1.col1, anon_1.col2 FROM (SELECT col1, col2,
ROW_NUMBER() OVER (ORDER BY col3) AS
mssql_rn FROM table WHERE t.x = :x_1) AS
anon_1 WHERE mssql_rn > :param_1 AND mssql_rn <= :param_2 + :param_1
请注意,使用 LIMIT 和/或 OFFSET 时,无论使用旧的还是新的 SQL Server 语法,该语句都必须具有 ORDER BY,否则将引发 CompileError
。
DDL 注释支持¶
注释支持(包括对 Table.comment
和 Column.comment
等属性的 DDL 渲染,以及反映这些注释的能力)得到支持,假设正在使用支持的 SQL Server 版本。如果在首次连接时检测到不支持的版本(例如 Azure Synapse)(基于 fn_listextendedproperty
SQL 函数的存在),则会禁用包括渲染和表注释反映在内的注释支持,因为这两个功能都依赖于并非所有后端类型都可用的 SQL Server 存储过程和函数。
要强制注释支持打开或关闭,绕过自动检测,请在 create_engine()
中设置参数 supports_comments
e = create_engine("mssql+pyodbc://u:p@dsn", supports_comments=False)
在版本 2.0 中添加: 为 SQL Server 方言添加了对表和列注释的支持,包括 DDL 生成和反映。
事务隔离级别¶
所有 SQL Server 方言都支持通过方言特定参数 create_engine.isolation_level
(create_engine()
接受)以及 Connection.execution_options.isolation_level
参数(传递给 Connection.execution_options()
)来设置事务隔离级别。此功能通过为每个新连接发出命令 SET TRANSACTION ISOLATION LEVEL <level>
来工作。
要使用 create_engine()
设置隔离级别
engine = create_engine(
"mssql+pyodbc://scott:tiger@ms_2008",
isolation_level="REPEATABLE READ"
)
要使用每个连接执行选项设置
connection = engine.connect()
connection = connection.execution_options(
isolation_level="READ COMMITTED"
)
的有效值为 isolation_level
包括
AUTOCOMMIT
- pyodbc / pymssql 特定READ COMMITTED
READ UNCOMMITTED
REPEATABLE READ
SERIALIZABLE
SNAPSHOT
- 特定于 SQL Server
还有更多隔离级别配置选项,例如与主 Engine
链接的“子引擎”对象,它们分别应用不同的隔离级别设置。有关背景信息,请参阅 设置事务隔离级别,包括 DBAPI 自动提交 中的讨论。
临时表/连接池资源重置¶
SQLAlchemy Engine
对象使用的 QueuePool
连接池实现包括 返回时重置 行为,该行为将在连接返回到池时调用 DBAPI .rollback()
方法。虽然此回滚将清除前一个事务使用的直接状态,但它不涵盖更广泛的会话级状态,包括临时表以及其他服务器状态,例如准备好的语句句柄和语句缓存。一个名为 sp_reset_connection
的未公开 SQL Server 过程是已知的解决此问题的变通方法,它将重置在连接上累积的大部分会话状态,包括临时表。
要安装 sp_reset_connection
作为执行返回时重置的方式,可以使用 PoolEvents.reset()
事件钩子,如下面的示例所示。 create_engine.pool_reset_on_return
参数设置为 None
,以便自定义方案可以完全替换默认行为。自定义钩子实现始终调用 .rollback()
,因为它通常很重要,DBAPI 对提交/回滚的跟踪将与事务状态保持一致。
from sqlalchemy import create_engine
from sqlalchemy import event
mssql_engine = create_engine(
"mssql+pyodbc://scott:tiger^5HHH@mssql2017:1433/test?driver=ODBC+Driver+17+for+SQL+Server",
# disable default reset-on-return scheme
pool_reset_on_return=None,
)
@event.listens_for(mssql_engine, "reset")
def _reset_mssql(dbapi_connection, connection_record, reset_state):
if not reset_state.terminate_only:
dbapi_connection.execute("{call sys.sp_reset_connection}")
# so that the DBAPI itself knows that the connection has been
# reset
dbapi_connection.rollback()
在版本 2.0.0b3 中更改: 在 PoolEvents.reset()
事件中添加了其他状态参数,并确保该事件对所有“重置”事件都调用,因此它适用于自定义“重置”处理程序。之前使用 PoolEvents.checkin()
处理程序的方案仍然可以使用。
可空性¶
MSSQL 支持三种级别的列可空性。默认可空性允许空值,并在 CREATE TABLE 结构中明确指定
name VARCHAR(20) NULL
如果指定了 nullable=None
,则不会进行任何指定。换句话说,将使用数据库配置的默认值。这将渲染
name VARCHAR(20)
如果 nullable
为 True
或 False
,则该列将分别为 NULL
或 NOT NULL
。
日期/时间处理¶
支持 DATE 和 TIME。绑定参数将转换为 datetime.datetime() 对象,这是大多数 MSSQL 驱动程序所需的,如果需要,结果将从字符串处理。DATE 和 TIME 类型不适用于 MSSQL 2005 及更早版本 - 如果检测到低于 2008 的服务器版本,则这些类型的 DDL 将作为 DATETIME 发出。
大型文本/二进制类型弃用¶
根据 SQL Server 2012/2014 文档,NTEXT
、TEXT
和 IMAGE
数据类型将在 SQL Server 的未来版本中删除。SQLAlchemy 通常将这些类型与 UnicodeText
、TextClause
和 LargeBinary
数据类型相关联。
为了适应此更改,在方言中添加了一个新的标志 deprecate_large_types
,该标志将在检测到正在使用的服务器版本时自动设置,除非用户另行设置。此标志的行为如下
当此标志为
True
时,UnicodeText
、TextClause
和LargeBinary
数据类型在用于渲染 DDL 时,将分别渲染为类型NVARCHAR(max)
、VARCHAR(max)
和VARBINARY(max)
。这是自添加此标志以来的新行为。当此标志为
False
时,UnicodeText
、TextClause
和LargeBinary
数据类型在用于渲染 DDL 时,将分别渲染为类型NTEXT
、TEXT
和IMAGE
。这是这些类型的长期行为。此标志在建立数据库连接之前的值为
None
。如果方言用于渲染 DDL 且未设置标志,则其解释与False
相同。在首次连接时,方言会检测是否正在使用 SQL Server 2012 或更高版本;如果标志仍为
None
,它会根据检测到的是 2012 或更高版本,将其设置为True
或False
。在创建方言时,可以将标志设置为
True
或False
,通常通过create_engine()
设置。eng = create_engine("mssql+pymssql://user:pass@host/db", deprecate_large_types=True)
在所有 SQLAlchemy 版本中,都可以完全控制是否渲染“旧”或“新”类型,方法是使用大写类型对象:
NVARCHAR
、VARCHAR
、VARBINARY
、TEXT
、NTEXT
、IMAGE
将始终保持固定,并始终输出完全相同的类型。
多部分架构名称¶
SQL Server 架构有时需要将其“架构”限定符分为多个部分,即包括数据库名称和所有者名称作为单独的标记,例如 mydatabase.dbo.some_table
。可以使用 Table.schema
参数一次性设置这些多部分名称 Table
Table(
"some_table", metadata,
Column("q", String(50)),
schema="mydatabase.dbo"
)
在执行表或组件反射等操作时,包含点的架构参数将被拆分为单独的“数据库”和“所有者”组件,以便正确查询 SQL Server 信息架构表,因为这两个值分别存储。此外,在为 DDL 或 SQL 渲染架构名称时,这两个组件将分别被引用,以用于区分大小写的名称和其他特殊字符。给定如下参数
Table(
"some_table", metadata,
Column("q", String(50)),
schema="MyDataBase.dbo"
)
上面的架构将被渲染为 [MyDataBase].dbo
,并且在反射中,也将使用“dbo”作为所有者和“MyDataBase”作为数据库名称。
要控制如何将架构名称分解为数据库/所有者,请在名称中指定括号(在 SQL Server 中是引用字符)。下面,“所有者”将被视为 MyDataBase.dbo
,“数据库”将为 None
Table(
"some_table", metadata,
Column("q", String(50)),
schema="[MyDataBase.dbo]"
)
要分别指定包含特殊字符或嵌入点的数据库和所有者名称,请使用两组括号
Table(
"some_table", metadata,
Column("q", String(50)),
schema="[MyDataBase.Period].[MyOwner.Dot]"
)
在版本 1.2 中更改: SQL Server 方言现在将方括号视为标识符分隔符,将架构拆分为单独的数据库和所有者标记,以允许点位于每个名称本身内部。
传统架构模式¶
MSSQL 方言的非常旧的版本引入了这样的行为:在 SELECT 语句中使用架构限定的表将自动别名化;给定一个表
account_table = Table(
'account', metadata,
Column('id', Integer, primary_key=True),
Column('info', String(100)),
schema="customer_schema"
)
这种渲染的传统模式假定“customer_schema.account”不会被 SQL 语句的所有部分接受,如下所示
>>> eng = create_engine("mssql+pymssql://mydsn", legacy_schema_aliasing=True)
>>> print(account_table.select().compile(eng))
SELECT account_1.id, account_1.info
FROM customer_schema.account AS account_1
这种行为模式现在默认情况下已关闭,因为它似乎没有任何作用;但是,如果遗留应用程序依赖于它,则可以使用 legacy_schema_aliasing
参数在 create_engine()
中使用,如上所示。
自版本 1.4 起弃用: legacy_schema_aliasing
标志现在已弃用,将在未来版本中删除。
聚集索引支持¶
MSSQL 方言通过 mssql_clustered
选项支持聚集索引(和主键)。此选项可用于 Index
、UniqueConstraint
和 PrimaryKeyConstraint
。对于索引,此选项可以与 mssql_columnstore
选项组合使用,以创建聚集列存储索引。
要生成聚集索引
Index("my_index", table.c.x, mssql_clustered=True)
这将把索引渲染为 CREATE CLUSTERED INDEX my_index ON table (x)
。
要生成聚集主键,请使用
Table('my_table', metadata,
Column('x', ...),
Column('y', ...),
PrimaryKeyConstraint("x", "y", mssql_clustered=True))
这将把表渲染为,例如
CREATE TABLE my_table (x INTEGER NOT NULL, y INTEGER NOT NULL,
PRIMARY KEY CLUSTERED (x, y))
类似地,我们可以使用以下方法生成聚集唯一约束
Table('my_table', metadata,
Column('x', ...),
Column('y', ...),
PrimaryKeyConstraint("x"),
UniqueConstraint("y", mssql_clustered=True),
)
要明确请求非聚集主键(例如,当需要单独的聚集索引时),请使用
Table('my_table', metadata,
Column('x', ...),
Column('y', ...),
PrimaryKeyConstraint("x", "y", mssql_clustered=False))
这将把表渲染为,例如
CREATE TABLE my_table (x INTEGER NOT NULL, y INTEGER NOT NULL,
PRIMARY KEY NONCLUSTERED (x, y))
列存储索引支持¶
MSSQL 方言通过 mssql_columnstore
选项支持列存储索引。此选项可用于 Index
。它可以与 mssql_clustered
选项组合使用,以创建聚集列存储索引。
要生成列存储索引
Index("my_index", table.c.x, mssql_columnstore=True)
这将把索引渲染为 CREATE COLUMNSTORE INDEX my_index ON table (x)
。
要生成聚集列存储索引,请不提供任何列
idx = Index("my_index", mssql_clustered=True, mssql_columnstore=True)
# required to associate the index with the table
table.append_constraint(idx)
上面的代码将把索引渲染为 CREATE CLUSTERED COLUMNSTORE INDEX my_index ON table
。
在版本 2.0.18 中新增。
MSSQL 特定索引选项¶
除了聚集之外,MSSQL 方言还支持 Index
的其他特殊选项。
INCLUDE¶
mssql_include
选项将为给定的字符串名称渲染 INCLUDE(colname)
Index("my_index", table.c.x, mssql_include=['y'])
将把索引渲染为 CREATE INDEX my_index ON table (x) INCLUDE (y)
过滤索引¶
mssql_where
选项将为给定的字符串名称渲染 WHERE(condition)
Index("my_index", table.c.x, mssql_where=table.c.x > 10)
将把索引渲染为 CREATE INDEX my_index ON table (x) WHERE x > 10
。
在版本 1.3.4 中新增。
索引排序¶
索引排序可通过函数表达式实现,例如
Index("my_index", table.c.x.desc())
将把索引渲染为 CREATE INDEX my_index ON table (x DESC)
另请参阅
兼容性级别¶
MSSQL 支持在数据库级别设置兼容性级别。这允许例如在 SQL2005 数据库服务器上运行与 SQL2000 兼容的数据库。server_version_info
将始终返回数据库服务器版本信息(在本例中为 SQL2005),而不是兼容性级别信息。因此,如果在向后兼容模式下运行,SQLAlchemy 可能会尝试使用数据库服务器无法解析的 T-SQL 语句。
触发器¶
默认情况下,SQLAlchemy 使用 OUTPUT INSERTED 通过 IDENTITY 列或其他服务器端默认值获取新生成的 主键值。MS-SQL 不允许在具有触发器的表上使用 OUTPUT INSERTED。要禁用在每个表的基础上使用 OUTPUT INSERTED,请为每个具有触发器的 Table
指定 implicit_returning=False
Table('mytable', metadata,
Column('id', Integer, primary_key=True),
# ...,
implicit_returning=False
)
声明式形式
class MyClass(Base):
# ...
__table_args__ = {'implicit_returning':False}
行计数支持 / ORM 版本控制¶
SQL Server 驱动程序可能在返回 UPDATE 或 DELETE 语句更新的行数方面存在限制。
在撰写本文时,PyODBC 驱动程序在使用 OUTPUT INSERTED 时无法返回行计数。因此,以前版本的 SQLAlchemy 对“ORM 版本控制”等功能存在限制,这些功能依赖于准确的行计数才能将版本号与匹配的行匹配。
SQLAlchemy 2.0 现在通过计算 RETURNING 中返回的行数来手动检索这些特定用例的“行计数”;因此,尽管驱动程序仍然存在此限制,但 ORM 版本控制功能不再受其影响。从 SQLAlchemy 2.0.5 开始,ORM 版本控制已针对 pyodbc 驱动程序完全重新启用。
在版本 2.0.5 中更改: ORM 版本控制支持已针对 pyodbc 驱动程序恢复。以前,在 ORM 刷新期间会发出有关版本控制不支持的警告。
启用快照隔离¶
SQL Server 具有默认的事务隔离模式,该模式会锁定整个表,即使是轻微的并发应用程序也会导致长时间持有锁和频繁的死锁。建议为整个数据库启用快照隔离,以支持现代级别的并发。这是通过在 SQL 提示符处执行以下 ALTER DATABASE 命令来实现的
ALTER DATABASE MyDatabase SET ALLOW_SNAPSHOT_ISOLATION ON
ALTER DATABASE MyDatabase SET READ_COMMITTED_SNAPSHOT ON
有关 SQL Server 快照隔离的背景信息,请访问 https://msdn.microsoft.com/en-us/library/ms175095.aspx.
SQL Server SQL 结构¶
对象名称 | 描述 |
---|---|
try_cast(expression, type_) |
为支持它的后端生成 |
- function sqlalchemy.dialects.mssql.try_cast(expression: _ColumnExpressionOrLiteralArgument[Any], type_: _TypeEngineArgument[_T]) → TryCast[_T]¶
为支持它的后端生成
TRY_CAST
表达式;这是一个CAST
,它对不可转换的转换返回 NULL。在 SQLAlchemy 中,此构造仅由 SQL Server 方言支持,如果在其他包含的后端上使用它,则会引发
CompileError
。但是,第三方后端也可能支持此构造。提示
由于
try_cast()
源自 SQL Server 方言,因此它既可以从sqlalchemy.
导入,也可以从sqlalchemy.dialects.mssql
导入。try_cast()
返回TryCast
的实例,并且通常的行为类似于Cast
构造;在 SQL 级别,CAST
和TRY_CAST
之间的区别在于,TRY_CAST
对不可转换的表达式(例如尝试将字符串"hi"
转换为整数值)返回 NULL。例如
from sqlalchemy import select, try_cast, Numeric stmt = select( try_cast(product_table.c.unit_price, Numeric(10, 4)) )
以上将在 Microsoft SQL Server 上呈现为
SELECT TRY_CAST (product_table.unit_price AS NUMERIC(10, 4)) FROM product_table
在版本 2.0.14 中添加:
try_cast()
已从 SQL Server 方言泛化为通用构造,可能得到其他方言的支持。
SQL Server 数据类型¶
与所有 SQLAlchemy 方言一样,所有已知对 SQL 服务器有效的 UPPERCASE 类型都可以从顶级方言导入,无论它们源自 sqlalchemy.types
还是本地方言
from sqlalchemy.dialects.mssql import (
BIGINT,
BINARY,
BIT,
CHAR,
DATE,
DATETIME,
DATETIME2,
DATETIMEOFFSET,
DECIMAL,
DOUBLE_PRECISION,
FLOAT,
IMAGE,
INTEGER,
JSON,
MONEY,
NCHAR,
NTEXT,
NUMERIC,
NVARCHAR,
REAL,
SMALLDATETIME,
SMALLINT,
SMALLMONEY,
SQL_VARIANT,
TEXT,
TIME,
TIMESTAMP,
TINYINT,
UNIQUEIDENTIFIER,
VARBINARY,
VARCHAR,
)
特定于 SQL Server 或具有 SQL Server 特定构造参数的类型如下
对象名称 | 描述 |
---|---|
MSSQL BIT 类型。 |
|
SQL Server DOUBLE PRECISION 数据类型。 |
|
MSSQL JSON 类型。 |
|
MSSQL NTEXT 类型,用于最多 2^30 个字符的可变长度 Unicode 文本。 |
|
SQL Server REAL 数据类型。 |
|
实现 SQL Server ROWVERSION 类型。 |
|
实现 SQL Server TIMESTAMP 类型。 |
|
MSSQL XML 类型。 |
- class sqlalchemy.dialects.mssql.BIT¶
MSSQL BIT 类型。
pyodbc 和 pymssql 都从 BIT 列中返回 Python <class ‘bool’> 作为值,因此只需子类化 Boolean。
成员
-
method
sqlalchemy.dialects.mssql.BIT.
__init__(create_constraint: bool = False, name: str | None = None, _create_events: bool = True, _adapted_from: SchemaType | None = None)¶ 继承自
sqlalchemy.types.Boolean.__init__
方法Boolean
构造一个布尔值。
- 参数:
create_constraint¶ –
默认为 False。如果布尔值作为 int/smallint 生成,也会在表上创建 CHECK 约束,以确保值为 1 或 0。
注意
强烈建议 CHECK 约束具有显式名称,以支持模式管理问题。这可以通过设置
Boolean.name
参数或设置适当的命名约定来实现;有关背景信息,请参阅 配置约束命名约定。在版本 1.4 中更改: - 此标志现在默认为 False,这意味着不会为非本机枚举类型生成 CHECK 约束。
name¶ – 如果生成 CHECK 约束,则指定约束的名称。
-
method
- class sqlalchemy.dialects.mssql.CHAR
SQL CHAR 类型。
类签名
class
sqlalchemy.dialects.mssql.CHAR
(sqlalchemy.types.String
)-
method
sqlalchemy.dialects.mssql.CHAR.
__init__(length: int | None = None, collation: str | None = None) 继承自
sqlalchemy.types.String.__init__
方法的String
创建一个保存字符串的类型。
- 参数:
length¶ – 可选,用于 DDL 和 CAST 表达式中的列长度。如果不会发出
CREATE TABLE
,则可以安全地省略。某些数据库可能需要length
用于 DDL,并且在发出CREATE TABLE
DDL 时,如果包含没有长度的VARCHAR
,将引发异常。该值是解释为字节还是字符取决于数据库。collation¶ –
可选,用于 DDL 和 CAST 表达式中的列级排序规则。使用 SQLite、MySQL 和 PostgreSQL 支持的 COLLATE 关键字渲染。例如
>>> from sqlalchemy import cast, select, String >>> print(select(cast('some string', String(collation='utf8'))))
SELECT CAST(:param_1 AS VARCHAR COLLATE utf8) AS anon_1注意
在大多数情况下,对于希望存储非 ASCII 数据的
Column
,应该使用Unicode
或UnicodeText
数据类型。这些数据类型将确保在数据库上使用正确的类型。
-
method
- class sqlalchemy.dialects.mssql.DATETIME2¶
类签名
class
sqlalchemy.dialects.mssql.DATETIME2
(sqlalchemy.dialects.mssql.base._DateTimeBase
,sqlalchemy.types.DateTime
)
- class sqlalchemy.dialects.mssql.DATETIMEOFFSET¶
类签名
class
sqlalchemy.dialects.mssql.DATETIMEOFFSET
(sqlalchemy.dialects.mssql.base._DateTimeBase
,sqlalchemy.types.DateTime
)
- class sqlalchemy.dialects.mssql.DOUBLE_PRECISION¶
SQL Server DOUBLE PRECISION 数据类型。
版本 2.0.11 中的新增功能。
- class sqlalchemy.dialects.mssql.IMAGE¶
成员
-
method
sqlalchemy.dialects.mssql.IMAGE.
__init__(length: int | None = None)¶ 继承自
sqlalchemy.types.LargeBinary.__init__
方法的LargeBinary
构建 LargeBinary 类型。
- 参数:
length¶ – 可选,用于 DDL 语句中的列长度,对于那些接受长度的二进制类型,例如 MySQL BLOB 类型。
-
method
- class sqlalchemy.dialects.mssql.JSON¶
MSSQL JSON 类型。
MSSQL 从 SQL Server 2016 开始支持 JSON 格式的数据。
在 DDL 级别的
JSON
数据类型将表示数据类型为NVARCHAR(max)
,但它还提供 JSON 级别的比较功能以及 Python 强制转换行为。每当基础
JSON
数据类型用于 SQL Server 后端时,将自动使用JSON
数据类型。另请参阅
JSON
- 通用跨平台 JSON 数据类型的基本文档。通过将操作调整为在数据库级别呈现
JSON_VALUE
或JSON_QUERY
函数,JSON
类型支持 JSON 值的持久化以及JSON
数据类型提供的核心索引操作。SQL Server
JSON
类型在查询 JSON 对象的元素时必须使用JSON_QUERY
和JSON_VALUE
函数。这两个函数有一个主要限制,即它们是相互排斥的,具体取决于要返回的对象类型。JSON_QUERY
函数仅返回 JSON 字典或列表,但不返回单个字符串、数字或布尔值元素;JSON_VALUE
函数仅返回单个字符串、数字或布尔值元素。如果这两个函数没有针对正确预期的值使用,它们将返回 NULL 或引发错误。为了处理这个棘手的要求,索引访问规则如下
从本身是 JSON 字典或列表的 JSON 中提取子元素时,应该使用
Comparator.as_json()
访问器stmt = select( data_table.c.data["some key"].as_json() ).where( data_table.c.data["some key"].as_json() == {"sub": "structure"} )
从本身是普通布尔值、字符串、整数或浮点数的 JSON 中提取子元素时,请在
Comparator.as_boolean()
、Comparator.as_string()
、Comparator.as_integer()
、Comparator.as_float()
中使用适当的方法stmt = select( data_table.c.data["some key"].as_string() ).where( data_table.c.data["some key"].as_string() == "some string" )
版本 1.4 中的新增功能。
成员
类签名
class
sqlalchemy.dialects.mssql.JSON
(sqlalchemy.types.JSON
)-
method
sqlalchemy.dialects.mssql.JSON.
__init__(none_as_null: bool = False)¶ 继承自
sqlalchemy.types.JSON.__init__
方法JSON
构造一个
JSON
类型。- 参数:
none_as_null=False¶ –
如果为 True,则将值
None
作为 SQL NULL 值持久化,而不是null
的 JSON 编码。请注意,当此标志为 False 时,null()
结构仍然可以用于持久化 NULL 值,该值可以直接作为参数值传递,由JSON
类型专门解释为 SQL NULLfrom sqlalchemy import null conn.execute(table.insert(), {"data": null()})
注意
JSON.none_as_null
不适用于传递给Column.default
和Column.server_default
的值;为这些参数传递的值None
意味着“没有默认值”。此外,在 SQL 比较表达式中使用时,Python 值
None
继续引用 SQL null,而不是 JSON NULL。JSON.none_as_null
标志明确指的是在 INSERT 或 UPDATE 语句中值的持久化。JSON.NULL
值应用于希望与 JSON null 进行比较的 SQL 表达式。另请参阅
- class sqlalchemy.dialects.mssql.MONEY¶
- class sqlalchemy.dialects.mssql.NCHAR
SQL NCHAR 类型。
类签名
class
sqlalchemy.dialects.mssql.NCHAR
(sqlalchemy.types.Unicode
)-
method
sqlalchemy.dialects.mssql.NCHAR.
__init__(length: int | None = None, collation: str | None = None) 继承自
sqlalchemy.types.String.__init__
方法的String
创建一个保存字符串的类型。
- 参数:
length¶ – 可选,用于 DDL 和 CAST 表达式的列长度。如果不会发出
CREATE TABLE
,可以安全地省略。某些数据库可能需要一个length
用于 DDL,并且在发出CREATE TABLE
DDL 时,如果包含没有长度的VARCHAR
,将引发异常。该值是解释为字节还是字符取决于具体数据库。collation¶ –
可选,用于 DDL 和 CAST 表达式中的列级排序规则。使用 SQLite、MySQL 和 PostgreSQL 支持的 COLLATE 关键字渲染。例如
>>> from sqlalchemy import cast, select, String >>> print(select(cast('some string', String(collation='utf8'))))
SELECT CAST(:param_1 AS VARCHAR COLLATE utf8) AS anon_1注意
在大多数情况下,对于希望存储非 ASCII 数据的
Column
,应该使用Unicode
或UnicodeText
数据类型。这些数据类型将确保在数据库上使用正确的类型。
-
method
- class sqlalchemy.dialects.mssql.NTEXT¶
MSSQL NTEXT 类型,用于最多 2^30 个字符的可变长度 Unicode 文本。
成员
-
method
sqlalchemy.dialects.mssql.NTEXT.
__init__(length: int | None = None, collation: str | None = None)¶ 继承自
sqlalchemy.types.String.__init__
方法的String
创建一个保存字符串的类型。
- 参数:
length¶ – 可选,用于 DDL 和 CAST 表达式的列长度。如果不会发出
CREATE TABLE
,可以安全地省略。某些数据库可能需要一个length
用于 DDL,并且在发出CREATE TABLE
DDL 时,如果包含没有长度的VARCHAR
,将引发异常。该值是解释为字节还是字符取决于具体数据库。collation¶ –
可选,用于 DDL 和 CAST 表达式中的列级排序规则。使用 SQLite、MySQL 和 PostgreSQL 支持的 COLLATE 关键字渲染。例如
>>> from sqlalchemy import cast, select, String >>> print(select(cast('some string', String(collation='utf8'))))
SELECT CAST(:param_1 AS VARCHAR COLLATE utf8) AS anon_1注意
在大多数情况下,对于希望存储非 ASCII 数据的
Column
,应该使用Unicode
或UnicodeText
数据类型。这些数据类型将确保在数据库上使用正确的类型。
-
method
- class sqlalchemy.dialects.mssql.NVARCHAR
SQL NVARCHAR 类型。
类签名
class
sqlalchemy.dialects.mssql.NVARCHAR
(sqlalchemy.types.Unicode
)-
method
sqlalchemy.dialects.mssql.NVARCHAR.
__init__(length: int | None = None, collation: str | None = None) 继承自
sqlalchemy.types.String.__init__
方法的String
创建一个保存字符串的类型。
- 参数:
length¶ – 可选,用于 DDL 和 CAST 表达式的列长度。如果不会发出
CREATE TABLE
,可以安全地省略。某些数据库可能需要一个length
用于 DDL,并且在发出CREATE TABLE
DDL 时,如果包含没有长度的VARCHAR
,将引发异常。该值是解释为字节还是字符取决于具体数据库。collation¶ –
可选,用于 DDL 和 CAST 表达式中的列级排序规则。使用 SQLite、MySQL 和 PostgreSQL 支持的 COLLATE 关键字渲染。例如
>>> from sqlalchemy import cast, select, String >>> print(select(cast('some string', String(collation='utf8'))))
SELECT CAST(:param_1 AS VARCHAR COLLATE utf8) AS anon_1注意
在大多数情况下,对于希望存储非 ASCII 数据的
Column
,应该使用Unicode
或UnicodeText
数据类型。这些数据类型将确保在数据库上使用正确的类型。
-
method
- class sqlalchemy.dialects.mssql.REAL¶
SQL Server REAL 数据类型。
类签名
class
sqlalchemy.dialects.mssql.REAL
(sqlalchemy.types.REAL
)
- class sqlalchemy.dialects.mssql.ROWVERSION¶
实现 SQL Server ROWVERSION 类型。
ROWVERSION 数据类型是 SQL Server 对 TIMESTAMP 数据类型的同义词,但是当前 SQL Server 文档建议对新数据类型使用 ROWVERSION。
ROWVERSION 数据类型不从数据库本身反映(例如,内省);返回的数据类型将是
TIMESTAMP
。这是一个只读数据类型,不支持 INSERT 值。
版本 1.2 中的新增内容。
另请参阅
成员
-
方法
sqlalchemy.dialects.mssql.ROWVERSION.
__init__(convert_int=False)¶ 继承自
sqlalchemy.dialects.mssql.base.TIMESTAMP.__init__
方法TIMESTAMP
构造一个 TIMESTAMP 或 ROWVERSION 类型。
- 参数:
convert_int¶ – 如果为 True,则二进制整数值在读取时将转换为整数。
版本 1.2 中的新增内容。
-
方法
- 类 sqlalchemy.dialects.mssql.SMALLDATETIME¶
成员
类签名
类
sqlalchemy.dialects.mssql.SMALLDATETIME
(sqlalchemy.dialects.mssql.base._DateTimeBase
,sqlalchemy.types.DateTime
)
- 类 sqlalchemy.dialects.mssql.SMALLMONEY¶
- 类 sqlalchemy.dialects.mssql.SQL_VARIANT¶
- 类 sqlalchemy.dialects.mssql.TEXT
SQL TEXT 类型。
类签名
类
sqlalchemy.dialects.mssql.TEXT
(sqlalchemy.types.Text
)-
方法
sqlalchemy.dialects.mssql.TEXT.
__init__(length: int | None = None, collation: str | None = None) 继承自
sqlalchemy.types.String.__init__
方法的String
创建一个保存字符串的类型。
- 参数:
length¶ – 可选,用于 DDL 和 CAST 表达式的列长度。如果不会发出任何
CREATE TABLE
,则可以安全地省略。某些数据库可能需要length
用于 DDL,并且当发出CREATE TABLE
DDL 时,如果包含没有长度的VARCHAR
,则会引发异常。该值是解释为字节还是字符取决于数据库。collation¶ –
可选,用于 DDL 和 CAST 表达式中的列级排序规则。使用 SQLite、MySQL 和 PostgreSQL 支持的 COLLATE 关键字渲染。例如
>>> from sqlalchemy import cast, select, String >>> print(select(cast('some string', String(collation='utf8'))))
SELECT CAST(:param_1 AS VARCHAR COLLATE utf8) AS anon_1注意
在大多数情况下,对于希望存储非 ASCII 数据的
Column
,应该使用Unicode
或UnicodeText
数据类型。这些数据类型将确保在数据库上使用正确的类型。
-
方法
- 类 sqlalchemy.dialects.mssql.TIME¶
- 类 sqlalchemy.dialects.mssql.TIMESTAMP¶
实现 SQL Server TIMESTAMP 类型。
请注意,这与 SQL 标准 TIMESTAMP 类型 **完全不同**,后者不受 SQL Server 支持。它是一种只读数据类型,不支持 INSERT 值。
版本 1.2 中的新增内容。
另请参阅
成员
类签名
类
sqlalchemy.dialects.mssql.TIMESTAMP
(sqlalchemy.types._Binary
)-
方法
sqlalchemy.dialects.mssql.TIMESTAMP.
__init__(convert_int=False)¶ 构造一个 TIMESTAMP 或 ROWVERSION 类型。
- 参数:
convert_int¶ – 如果为 True,则二进制整数值在读取时将转换为整数。
版本 1.2 中的新增内容。
-
方法
- 类 sqlalchemy.dialects.mssql.TINYINT¶
- 类 sqlalchemy.dialects.mssql.UNIQUEIDENTIFIER¶
成员
-
method
sqlalchemy.dialects.mssql.UNIQUEIDENTIFIER.
__init__(as_uuid: bool = True)¶ 构造一个
UNIQUEIDENTIFIER
类型。- 参数:
as_uuid=True¶ –
如果为 True,则值将被解释为 Python uuid 对象,通过 DBAPI 在字符串之间进行转换。
-
method
- class sqlalchemy.dialects.mssql.VARBINARY
MSSQL VARBINARY 类型。
此类型为核心
VARBINARY
类型添加了额外的功能,包括“deprecate_large_types”模式,其中将渲染VARBINARY(max)
或 IMAGE,以及 SQL ServerFILESTREAM
选项。另请参阅
类签名
class
sqlalchemy.dialects.mssql.VARBINARY
(sqlalchemy.types.VARBINARY
,sqlalchemy.types.LargeBinary
)-
method
sqlalchemy.dialects.mssql.VARBINARY.
__init__(length=None, filestream=False) 构造一个 VARBINARY 类型。
-
method
- class sqlalchemy.dialects.mssql.VARCHAR
SQL VARCHAR 类型。
类签名
class
sqlalchemy.dialects.mssql.VARCHAR
(sqlalchemy.types.String
)-
method
sqlalchemy.dialects.mssql.VARCHAR.
__init__(length: int | None = None, collation: str | None = None) 继承自
sqlalchemy.types.String.__init__
方法的String
创建一个保存字符串的类型。
- 参数:
length¶ – 可选,用于 DDL 和 CAST 表达式的列长度。如果不会发出
CREATE TABLE
,则可以安全地省略。某些数据库可能需要length
用于 DDL,并且在发出CREATE TABLE
DDL 时,如果包含没有长度的VARCHAR
,将引发异常。值是否被解释为字节或字符取决于数据库。collation¶ –
可选,用于 DDL 和 CAST 表达式中的列级排序规则。使用 SQLite、MySQL 和 PostgreSQL 支持的 COLLATE 关键字渲染。例如
>>> from sqlalchemy import cast, select, String >>> print(select(cast('some string', String(collation='utf8'))))
SELECT CAST(:param_1 AS VARCHAR COLLATE utf8) AS anon_1注意
在大多数情况下,对于希望存储非 ASCII 数据的
Column
,应该使用Unicode
或UnicodeText
数据类型。这些数据类型将确保在数据库上使用正确的类型。
-
method
- class sqlalchemy.dialects.mssql.XML¶
MSSQL XML 类型。
这是一个用于反射目的的占位符类型,不包含任何 Python 端数据类型支持。它目前也不支持其他参数,例如“CONTENT”、“DOCUMENT”、“xml_schema_collection”。
成员
类签名
-
method
sqlalchemy.dialects.mssql.XML.
__init__(length: int | None = None, collation: str | None = None)¶ 继承自
sqlalchemy.types.String.__init__
方法的String
创建一个保存字符串的类型。
- 参数:
length¶ – 可选,用于 DDL 和 CAST 表达式的列长度。如果不会发出
CREATE TABLE
,则可以安全地省略。某些数据库可能需要length
用于 DDL,并且在发出CREATE TABLE
DDL 时,如果包含没有长度的VARCHAR
,将引发异常。值是否被解释为字节或字符取决于数据库。collation¶ –
可选,用于 DDL 和 CAST 表达式中的列级排序规则。使用 SQLite、MySQL 和 PostgreSQL 支持的 COLLATE 关键字渲染。例如
>>> from sqlalchemy import cast, select, String >>> print(select(cast('some string', String(collation='utf8'))))
SELECT CAST(:param_1 AS VARCHAR COLLATE utf8) AS anon_1注意
在大多数情况下,对于希望存储非 ASCII 数据的
Column
,应该使用Unicode
或UnicodeText
数据类型。这些数据类型将确保在数据库上使用正确的类型。
-
method
PyODBC¶
通过 PyODBC 驱动程序支持 Microsoft SQL Server 数据库。
DBAPI¶
PyODBC 的文档和下载信息(如果适用)可在以下位置获取:https://pypi.ac.cn/project/pyodbc/
连接¶
连接字符串
mssql+pyodbc://<username>:<password>@<dsnname>
连接到 PyODBC¶
此处的 URL 将被转换为 PyODBC 连接字符串,如 ConnectionStrings 中所述。
DSN 连接¶
ODBC 中的 DSN 连接意味着在客户端机器上配置了预先存在的 ODBC 数据源。然后,应用程序指定此数据源的名称,该名称包含诸如所使用的特定 ODBC 驱动程序以及数据库的网络地址之类的详细信息。假设在客户端上配置了数据源,则基本的基于 DSN 的连接看起来像
engine = create_engine("mssql+pyodbc://scott:tiger@some_dsn")
上面的内容将以下连接字符串传递给 PyODBC
DSN=some_dsn;UID=scott;PWD=tiger
如果省略用户名和密码,则 DSN 表单还将在 ODBC 字符串中添加 Trusted_Connection=yes
指令。
主机名连接¶
pyodbc 也支持基于主机名的连接。这些通常比 DSN 更易于使用,并且具有额外的优势,即要连接到的特定数据库名称可以在 URL 中本地指定,而不是作为数据源配置的一部分固定下来。
使用主机名连接时,还必须在 URL 的查询参数中指定驱动程序名称。由于这些名称通常包含空格,因此名称必须进行 URL 编码,这意味着使用加号来代替空格
engine = create_engine("mssql+pyodbc://scott:tiger@myhost:port/databasename?driver=ODBC+Driver+17+for+SQL+Server")
driver
关键字对于 pyodbc 方言很重要,必须以小写形式指定。
在查询字符串中传递的任何其他名称都将通过 pyodbc 连接字符串传递,例如 authentication
、TrustServerCertificate
等。多个关键字参数必须用一个与号 (&
) 分隔;这些将在内部生成 pyodbc 连接字符串时转换为分号
e = create_engine(
"mssql+pyodbc://scott:tiger@mssql2017:1433/test?"
"driver=ODBC+Driver+18+for+SQL+Server&TrustServerCertificate=yes"
"&authentication=ActiveDirectoryIntegrated"
)
可以使用 URL
构造等效的 URL
from sqlalchemy.engine import URL
connection_url = URL.create(
"mssql+pyodbc",
username="scott",
password="tiger",
host="mssql2017",
port=1433,
database="test",
query={
"driver": "ODBC Driver 18 for SQL Server",
"TrustServerCertificate": "yes",
"authentication": "ActiveDirectoryIntegrated",
},
)
传递精确的 Pyodbc 字符串¶
PyODBC 连接字符串也可以使用参数 odbc_connect
直接以 pyodbc 的格式发送,如 PyODBC 文档 中所述。使用 URL
对象可以使此操作更容易
from sqlalchemy.engine import URL
connection_string = "DRIVER={SQL Server Native Client 10.0};SERVER=dagger;DATABASE=test;UID=user;PWD=password"
connection_url = URL.create("mssql+pyodbc", query={"odbc_connect": connection_string})
engine = create_engine(connection_url)
使用访问令牌连接到数据库¶
一些数据库服务器被设置为仅接受访问令牌进行登录。例如,SQL Server 允许使用 Azure Active Directory 令牌连接到数据库。这需要使用 azure-identity
库创建凭据对象。有关身份验证步骤的更多信息,请参阅 Microsoft 的文档。
获取引擎后,每次请求连接时,都需要将凭据发送到 pyodbc.connect
。一种方法是在引擎上设置一个事件监听器,将凭据令牌添加到方言的连接调用中。这在 生成动态身份验证令牌 中有更详细的说明。对于 SQL Server,这作为 ODBC 连接属性传递,并使用 Microsoft 描述的数据结构。
以下代码片段将创建一个使用 Azure 凭据连接到 Azure SQL 数据库的引擎
import struct
from sqlalchemy import create_engine, event
from sqlalchemy.engine.url import URL
from azure import identity
SQL_COPT_SS_ACCESS_TOKEN = 1256 # Connection option for access tokens, as defined in msodbcsql.h
TOKEN_URL = "https://database.windows.net/" # The token URL for any Azure SQL database
connection_string = "mssql+pyodbc://@my-server.database.windows.net/myDb?driver=ODBC+Driver+17+for+SQL+Server"
engine = create_engine(connection_string)
azure_credentials = identity.DefaultAzureCredential()
@event.listens_for(engine, "do_connect")
def provide_token(dialect, conn_rec, cargs, cparams):
# remove the "Trusted_Connection" parameter that SQLAlchemy adds
cargs[0] = cargs[0].replace(";Trusted_Connection=Yes", "")
# create token credential
raw_token = azure_credentials.get_token(TOKEN_URL).token.encode("utf-16-le")
token_struct = struct.pack(f"<I{len(raw_token)}s", len(raw_token), raw_token)
# apply it to keyword arguments
cparams["attrs_before"] = {SQL_COPT_SS_ACCESS_TOKEN: token_struct}
提示
目前,当没有用户名或密码时,Trusted_Connection
令牌由 SQLAlchemy pyodbc 方言添加。这需要根据 Microsoft 的 Azure 访问令牌文档 移除,该文档指出使用访问令牌时的连接字符串不应包含 UID
、PWD
、Authentication
或 Trusted_Connection
参数。
避免 Azure Synapse Analytics 上与事务相关的异常¶
Azure Synapse Analytics 在其事务处理方面与普通 SQL Server 有很大区别;在某些情况下,Synapse 事务中的错误会导致它在服务器端被任意终止,然后导致 DBAPI .rollback()
方法(以及 .commit()
)失败。此问题阻止了通常的 DBAPI 协议,该协议允许 .rollback()
在没有事务的情况下静默通过,因为驱动程序不期望这种情况。此失败的症状是,在尝试发出 .rollback()
后,操作出现某种错误,则会出现类似“找不到对应的事务。(111214)”的错误消息的异常。
此特定情况可以通过将 ignore_no_transaction_on_rollback=True
传递给 SQL Server 方言(通过 create_engine()
函数)来处理,如下所示
engine = create_engine(connection_url, ignore_no_transaction_on_rollback=True)
使用上述参数,方言将在 connection.rollback()
期间捕获 ProgrammingError
异常,并在错误消息包含代码 111214
时发出警告,但不会引发异常。
New in version 1.4.40: 添加了 ignore_no_transaction_on_rollback=True
参数。
为 Azure SQL 数据仓库 (DW) 连接启用自动提交¶
Azure SQL 数据仓库不支持事务,这可能会导致 SQLAlchemy 的“自动开始”(以及隐式提交/回滚)行为出现问题。我们可以通过在 pyodbc 和引擎级别启用自动提交来避免这些问题
connection_url = sa.engine.URL.create(
"mssql+pyodbc",
username="scott",
password="tiger",
host="dw.azure.example.com",
database="mydb",
query={
"driver": "ODBC Driver 17 for SQL Server",
"autocommit": "True",
},
)
engine = create_engine(connection_url).execution_options(
isolation_level="AUTOCOMMIT"
)
避免将大型字符串参数发送为 TEXT/NTEXT¶
默认情况下,出于历史原因,Microsoft 的 SQL Server ODBC 驱动程序将长字符串参数(大于 4000 个 SBCS 字符或 2000 个 Unicode 字符)发送为 TEXT/NTEXT 值。TEXT 和 NTEXT 已被弃用多年,并且开始导致与较新版本的 SQL_Server/Azure 的兼容性问题。例如,请参阅 此问题。
从 ODBC Driver 18 for SQL Server 开始,我们可以覆盖旧行为,并使用 LongAsMax=Yes
连接字符串参数将长字符串传递为 varchar(max)/nvarchar(max)
connection_url = sa.engine.URL.create(
"mssql+pyodbc",
username="scott",
password="tiger",
host="mssqlserver.example.com",
database="mydb",
query={
"driver": "ODBC Driver 18 for SQL Server",
"LongAsMax": "Yes",
},
)
Pyodbc 池/连接关闭行为¶
PyODBC 默认使用内部 池,这意味着连接的存活时间将比 SQLAlchemy 自身中的连接更长。由于 SQLAlchemy 有自己的池行为,因此通常最好禁用此行为。此行为只能在 PyODBC 模块级别全局禁用,在建立任何连接之前
import pyodbc
pyodbc.pooling = False
# don't use the engine before pooling is set to False
engine = create_engine("mssql+pyodbc://user:pass@dsn")
如果此变量保持其默认值 True
,应用程序将继续维护活动的数据库连接,即使 SQLAlchemy 引擎本身完全丢弃连接或引擎被处置。
另请参阅
池 - 在 PyODBC 文档中。
驱动程序/Unicode 支持¶
PyODBC 最适合与 Microsoft ODBC 驱动程序配合使用,尤其是在 Python 2 和 Python 3 上的 Unicode 支持方面。
在 Linux 或 OSX 上将 FreeTDS ODBC 驱动程序与 PyODBC 结合使用不推荐;在历史上,该领域存在许多与 Unicode 相关的错误,包括在 Microsoft 为 Linux 和 OSX 提供 ODBC 驱动程序之前。现在 Microsoft 为所有平台提供驱动程序,对于 PyODBC 支持,建议使用这些驱动程序。FreeTDS 对于非 ODBC 驱动程序(如 pymssql)仍然具有相关性,它在该驱动程序中运行良好。
行计数支持¶
从 SQLAlchemy 2.0.5 开始,SQLAlchemy ORM 的“版本化行”功能与 Pyodbc 的先前限制已得到解决。请参阅 行计数支持/ORM 版本控制 中的说明。
快速 executemany 模式¶
PyODBC 驱动程序包含对“快速 executemany”执行模式的支持,该模式在使用 Microsoft ODBC 驱动程序时,可大幅减少 DBAPI executemany()
调用的往返次数,前提是批处理大小有限,且适合内存。该功能通过在使用 executemany 调用时,在 DBAPI 游标上设置属性 .fast_executemany
来启用。SQLAlchemy PyODBC SQL Server 方言通过将 fast_executemany
参数传递给 create_engine()
来支持此参数,前提是仅使用 Microsoft ODBC 驱动程序
engine = create_engine(
"mssql+pyodbc://scott:tiger@mssql2017:1433/test?driver=ODBC+Driver+17+for+SQL+Server",
fast_executemany=True)
Changed in version 2.0.9: - fast_executemany
参数现在具有其预期的效果,即此 PyODBC 功能对所有使用多个参数集执行且不包含 RETURNING 的 INSERT 语句生效。以前,SQLAlchemy 2.0 的 insertmanyvalues 功能会导致 fast_executemany
在大多数情况下(即使指定)也不会使用。
New in version 1.3.
另请参阅
快速 executemany - 在 github 上
Setinputsizes 支持¶
从 2.0 版本开始,pyodbc cursor.setinputsizes()
方法用于所有语句执行,除了 cursor.executemany()
调用(当 fast_executemany=True 时,它不支持该调用)(假设 insertmanyvalues 保持启用状态,“fastexecutemany”在任何情况下都不会针对 INSERT 语句生效)。
可以通过将 use_setinputsizes=False
传递给 create_engine()
来禁用 cursor.setinputsizes()
的使用。
当 use_setinputsizes
保持其默认值 True
时,可以以编程方式自定义传递给 cursor.setinputsizes()
的特定每类型符号,使用 DialectEvents.do_setinputsizes()
钩子。有关用法示例,请参阅该方法。
Changed in version 2.0: mssql+pyodbc 方言现在默认情况下对所有语句执行使用 use_setinputsizes=True
,除了 cursor.executemany()
调用(当 fast_executemany=True 时)。可以通过将 use_setinputsizes=False
传递给 create_engine()
来关闭此行为。
pymssql¶
通过 pymssql 驱动程序支持 Microsoft SQL Server 数据库。
连接¶
连接字符串
mssql+pymssql://<username>:<password>@<freetds_name>/?charset=utf8
pymssql 是一个 Python 模块,它围绕 FreeTDS 提供 Python DBAPI 接口。
Changed in version 2.0.5: pymssql 已恢复到 SQLAlchemy 的持续集成测试
aioodbc¶
通过 aioodbc 驱动程序支持 Microsoft SQL Server 数据库。
DBAPI¶
aioodbc 的文档和下载信息(如果适用)可从以下网址获取:https://pypi.ac.cn/project/aioodbc/
连接¶
连接字符串
mssql+aioodbc://<username>:<password>@<dsnname>
使用 aioodbc 驱动程序(它本身是 pyodbc 周围的线程包装器)以 asyncio 样式支持 SQL Server 数据库。
New in version 2.0.23: 添加了 mssql+aioodbc 方言,该方言构建在 pyodbc 和一般的 aio* 方言体系结构之上。
aioodbc 方言使用特殊的 asyncio 中介层,可以用作 SQLAlchemy 异步 扩展包的后端。
此驱动程序的大多数行为和注意事项与 SQL Server 上使用的 pyodbc 方言相同;有关一般背景信息,请参见 PyODBC。
此方言通常只应与 create_async_engine()
引擎创建函数一起使用;连接样式与 pyodbc 部分中记录的样式相同。
from sqlalchemy.ext.asyncio import create_async_engine
engine = create_async_engine(
"mssql+aioodbc://scott:tiger@mssql2017:1433/test?"
"driver=ODBC+Driver+18+for+SQL+Server&TrustServerCertificate=yes"
)
flambé! 龙和 炼金术士 图像设计由 Rotem Yaari 创建并慷慨捐赠。
使用 Sphinx 7.2.6 创建。文档上次生成时间:2024 年 11 月 8 日星期五,美国东部时间上午 8:41:19。