Microsoft SQL 服务器
Support for the Microsoft SQL Server database.
The following table summarizes current support levels for database release versions.
外部方言
除了上述具有本机SQLAlChemy支持的DBAPI层之外,还有与SQL Server兼容的其他DBAPI层的第三方方言。请参阅上的“外部方言”列表。 方言 佩奇。
自动增量行为/标识列
SQL Server使用 IDENTITY
构造,它可以放置在表中的任何单个整数列上。SQL炼金术考虑 IDENTITY
在整数主键列的默认“autoincrement”行为中,如中所述 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
不需要,请指定 False
对于 Column.autoincrement
标志,在第一个整数主键列上::
m = MetaData() t = Table('t', m, Column('id', Integer, primary_key=True, autoincrement=False), Column('x', Integer)) m.create_all(engine)
添加 IDENTITY
关键字到非主键列,请指定 True
对于 Column.autoincrement
所需的标志 Column
反对,并确保 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 版更改: 补充 Identity
在a中构造 Column
指定标识的起始参数和增量参数。这些替代了 Sequence
对象以指定这些值。
1.4 版后已移除: 这个 mssql_identity_start
和 mssql_identity_increment
参数到 Column
不推荐使用,是否应该用 Identity
对象。指定两种配置标识的方法将导致编译错误。这些选项也不再作为 dialect_options
键入 Inspector.get_columns()
. 使用中的信息 identity
而不是钥匙。
1.3 版后已移除: 使用 Sequence
指定身份特征已弃用,并将在将来的版本中删除。请使用 Identity
对象参数 Identity.start
和 Identity.increment
。
在 1.4 版更改: 删除了使用 Sequence
对象来修改标识特征。 Sequence
对象现在只操作真正的T-SQL序列类型。
注解
表上只能有一个标识列。使用时 autoincrement=True
要启用IDENTITY关键字,SQLAlchemy不会防止同时指定选项的多个列。SQL Server数据库将拒绝 CREATE TABLE
语句。
注解
试图为标记有标识的列提供值的INSERT语句将被SQL Server拒绝。要接受该值,必须启用会话级选项“设置标识插入”。当使用核心时,SQLAlchemy SQL Server方言将自动执行此操作 Insert
构造;如果执行为标识列指定了一个值,则将为该语句的调用范围启用“identityu insert”选项。但是,此方案的性能不高,不应依赖于正常使用。如果表在其整数主键列中实际上不需要标识行为,则在创建表时应通过确保 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 test ( id INTEGER NOT NULL IDENTITY(100,10) PRIMARY KEY, name VARCHAR(20) NULL, )
注解
这个 Identity
对象除了支持 start
和 increment
. SQL Server不支持它们,在生成创建表ddl时将忽略它们。
在 1.3.19 版更改: 这个 Identity
对象现在用于影响 IDENTITY
发电机A Column
在SQL Server下。以前, Sequence
使用了对象。由于SQL Server现在支持将实数序列作为单独的构造, Sequence
从SQLAlchemy 1.4版开始,将以正常方式运行。
插入行为
处理 IDENTITY
插入时的列涉及两个关键技术。最常见的是能够获取给定的“最后插入的值” IDENTITY
列,在许多情况下,SQLAlchemy隐式执行的过程,最重要的是在ORM中。
获取此值的过程有几个变体:
在大多数情况下,返回与SQL Server上的insert语句一起使用,以获取新生成的主键值:
INSERT INTO t (x) OUTPUT inserted.id VALUES (?)
当返回不可用或已被禁用时,通过
implicit_returning=False
,要么scope_identity()
函数或@@identity
使用变量;行为因后端而异:使用pyodbc时,
; select scope_identity()
将附加到insert语句的末尾;将获取第二个结果集以接收该值。给一张桌子作为:t = Table('t', m, Column('id', Integer, primary_key=True), Column('x', Integer), implicit_returning=False)
插入内容如下:
INSERT INTO t (x) VALUES (?); select scope_identity()
其他方言如pymsql将调用
SELECT scope_identity() AS lastrowid
在insert语句之后。如果旗use_scope_identity=False
传递给create_engine()
,声明SELECT @@identity AS lastrowid
而是使用。
包含 IDENTITY
列将禁止显式引用标识列的INSERT语句。SQLAlchemy方言将检测使用核心创建的插入构造的时间 insert()
构造(不是纯字符串SQL),引用标识列,在这种情况下将发出 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})
上面的列将使用标识创建,但是我们发出的insert语句指定了显式值。在echo输出中,我们可以看到sqlacalchemy如何处理这一点:
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
对象现在创建“真实”序列,即。, CREATE SEQUENCE
. 为了与其他方言兼容, Sequence
默认为起始值1,即使T-SQL的默认值是-9223372036854775808。
1.4.0 新版功能.
varchar/nvarchar上的最大值
SQL Server支持 VARCHAR
和 NVARCHAR
数据类型,表示“可能的最大长度”。方言当前在基类型中将其处理为“无”的长度,而不是提供这些类型的方言特定版本,以便指定基类型,例如 VARCHAR(None)
可以在多个后端上假定“unengthed”行为,而不使用特定于方言的类型。
要生成最大长度的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
极限/偏移支撑
从SQLServer2012开始,MSSQL通过“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和no OFFSET的语句,SQL Server的所有版本都支持TOP关键字。当不存在OFFSET子句时,此语法用于所有SQL Server版本。例如:
select(some_table).limit(5)
将呈现类似于:
SELECT TOP 5 col1, col2.. FROM table
对于SQL Server 2012之前的SQL Server版本,将使用 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
提高了。
事务隔离级别
所有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
1.2 新版功能: 添加自动提交隔离级别设置
参见
空属性
MSSQL支持三个级别的列可空性。默认的可空性允许空值,并且在创建表构造中是显式的::
name VARCHAR(20) NULL
如果 nullable=None
如果指定,则不制定规范。换句话说,使用数据库的配置默认值。这将呈现:
name VARCHAR(20)
如果 nullable
是 True
或 False
那么这个列将是 NULL
或 NOT NULL
分别。
日期/时间处理
支持日期和时间。绑定参数根据大多数MSSQL驱动程序的要求转换为datetime.datetime()对象,如果需要,将从字符串中处理结果。日期和时间类型不适用于MSSQL2005和以前版本-如果检测到低于2008的服务器版本,这些类型的DDL将作为日期时间发出。
大文本/二进制类型取消预测
每 SQL Server 2012/2014 Documentation ,即 NTEXT
, TEXT
和 IMAGE
数据类型将在将来的版本中从SQL Server中删除。SQLAlChemy通常将这些类型与 UnicodeText
, TextClause
和 LargeBinary
数据类型。
为了适应这种变化,新的标志 deprecate_large_types
添加到方言中,如果用户未进行其他设置,则将根据正在使用的服务器版本检测自动进行设置。此标志的行为如下:
当此标志为
True
, theUnicodeText
,TextClause
和LargeBinary
当用于呈现DDL时,数据类型将呈现这些类型NVARCHAR(max)
,VARCHAR(max)
和VARBINARY(max)
,分别。这是添加此标志后的新行为。当此标志为
False
, theUnicodeText
,TextClause
和LargeBinary
当用于呈现DDL时,数据类型将呈现这些类型NTEXT
,TEXT
和IMAGE
,分别。这是这些类型的长期行为。标志以值开头
None
,在建立数据库连接之前。如果方言用于呈现没有设置标志的DDL,则解释为False
.在第一次连接时,方言将检测SQL Server 2012或更高版本是否在使用中;如果标志仍在
None
它把它设置为True
或False
基于是否检测到2012或更高版本。标志可以设置为
True
或False
创建方言时,通常通过create_engine()
::eng = create_engine("mssql+pymssql://user:pass@host/db", deprecate_large_types=True)
在所有SQLAlchemy版本中,通过使用大写类型对象,可以完全控制呈现“旧”类型还是“新”类型:
NVARCHAR
,VARCHAR
,VARBINARY
,TEXT
,NTEXT
,IMAGE
将始终保持固定,并始终准确输出该类型。
1.0.0 新版功能.
多部分架构名称
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
“数据库”将为无:
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.1 版更改: 这个 legacy_schema_aliasing
版本1.0.5中引入的标志,允许禁用模式的遗留模式,现在默认为false。
1.4 版后已移除: 这个 legacy_schema_aliasing
标志现在已弃用,将在将来的版本中删除。
聚集索引支持
MSSQL方言通过 mssql_clustered
选择权。此选项可用于 Index
, UniqueConstraint
. 和 PrimaryKeyConstraint
.
要生成聚集索引,请执行以下操作:
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))
在 1.1 版更改: 这个 mssql_clustered
选项现在默认为无,而不是假。 mssql_clustered=False
现在显式地呈现非聚集子句,而none则完全省略clustered子句,从而使SQL Server默认值生效。
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(条件)::
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使用插入的输出通过标识列或其他服务器端默认值获取新生成的主键值。MS-SQL不允许在具有触发器的表上使用插入的输出。要禁用按表插入的输出,请指定 implicit_returning=False
对于每一个 Table
触发条件:
Table('mytable', metadata, Column('id', Integer, primary_key=True), # ..., implicit_returning=False )
声明形式:
class MyClass(Base): # ... __table_args__ = {'implicit_returning':False}
也可以使用 implicit_returning=False
争论 create_engine()
.
行数支持/ORM版本控制
SQL Server驱动程序返回更新或删除语句中更新的行数的能力可能有限。
在撰写本文时,当使用插入的输出时,pyodbc驱动程序无法返回行数。这会影响SQLAlchemy ORM的版本控制功能,在许多情况下,服务器端的值生成器正在使用中,当版本控制操作可以成功时,ORM不能总是检查更新或删除语句是否与预期的行数匹配,这就是它验证版本标识符是否匹配的方式。出现这种情况时,将发出警告,但操作将继续。
通过设置 Table.implicit_returning
旗到 False
关于某一特定 Table
,在声明式中如下所示:
class MyTable(Base): __tablename__ = 'mytable' id = Column(Integer, primary_key=True) stuff = Column(String(10)) timestamp = Column(TIMESTAMP(), default=text('DEFAULT')) __mapper_args__ = { 'version_id_col': timestamp, 'version_id_generator': False, } __table_args__ = { 'implicit_returning': False }
启用快照隔离
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构造
Object Name | Description |
---|---|
try_cast(*arg, **kw) | 创建TRYu CAST表达式。 |
- function sqlalchemy.dialects.mssql.try_cast(*arg, **kw)
与所有的SQLAlchemy方言一样,已知对SQL Server有效的所有大写类型都可以从顶级方言导入,无论它们是否源自
sqlalchemy.types
或者来自当地方言:from sqlalchemy.dialects.mssql import \ BIGINT, BINARY, BIT, CHAR, DATE, DATETIME, DATETIME2, \ DATETIMEOFFSET, DECIMAL, 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的构造参数的类型如下:
Object Name Description MSSQL位类型。
SQL字符类型。
MSSQL JSON类型。
SQL NChar类型。
mssql ntext类型,用于长度不超过2^30个字符的Unicode文本。
SQL nvarchar类型。
实现SQL Server行版本类型。
SQL文本类型。
实现SQL Server时间戳类型。
SQL varchar类型。
MSSQL XML类型。
- class sqlalchemy.dialects.mssql.BIT(create_constraint=False, name=None, _create_events=True)
Support for the Microsoft SQL Server database via the PyODBC driver.
DBAPI
Documentation and download information (if applicable) for PyODBC is available at: https://pypi.org/project/pyodbc/
Connecting
Connect String:
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表单还将添加
Trusted_Connection=yes
ODBC字符串的指令。主机名连接
pyodbc也支持基于主机名的连接。它们通常比DSN更易于使用,而且还有一个额外的优点,即要连接的特定数据库名称可以在URL中本地指定,而不是作为数据源配置的一部分进行固定。
使用主机名连接时,还必须在URL的查询参数中指定驱动程序名称。由于这些名称中通常有空格,因此名称必须是URL编码的,这意味着对空格使用加号:
engine = create_engine("mssql+pyodbc://scott:tiger@myhost:port/databasename?driver=ODBC+Driver+17+for+SQL+Server")
要传递给的由Pyodbc方言解释的其他关键字
pyodbc.connect()
在DSN和主机名情况下都包括:odbc_autotranslate
,ansi
,unicode_results
,autocommit
,authentication
。请注意,为了使方言能够识别这些关键字(包括driver
上面的关键字)它们必须全部为小写。多个附加关键字参数必须用与号分隔 (&
),而不是分号::engine = create_engine( "mssql+pyodbc://scott:tiger@myhost:49242/databasename" "?driver=ODBC+Driver+17+for+SQL+Server" "&authentication=ActiveDirectoryIntegrated" )
可以使用以下命令构建等效的URL
URL
::from sqlalchemy.engine import URL connection_url = URL.create( "mssql+pyodbc", username="scott", password="tiger", host="myhost", port=49242, database="databasename", query={ "driver": "ODBC Driver 17 for SQL Server", "authentication": "ActiveDirectoryIntegrated", }, )
传递精确的pyodbc字符串
PyODBC连接字符串也可以直接以pyodbc的格式发送,如 the PyODBC documentation ,使用参数
odbc_connect
。一个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's documentation 。获得引擎后,需要将凭据发送到
pyodbc.connect
每次请求连接时。要做到这一点,一种方法是在引擎上设置一个事件侦听器,将凭据令牌添加到方言的CONNECT调用中。中更广泛地讨论了这一点。 生成动态身份验证令牌 。特别是对于SQL Server,它作为具有数据结构的ODBC连接属性传递 described by 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的 documentation for Azure access tokens ,声明使用访问令牌时的连接字符串不得包含UID
,PWD
,Authentication
或Trusted_Connection
参数。为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" )
Pyodbc池/连接关闭行为
PyODBC使用内部 pooling 默认情况下,这意味着连接的寿命将比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")
如果此变量的默认值为left
True
, 应用程序将继续保持活动的数据库连接 ,即使SQLAlchemy引擎本身完全放弃了连接,或者如果引擎被释放。参见
pooling -在PyODBC文档中。
驱动程序/Unicode支持
pyodbc最适用于Microsoft ODBC驱动程序,特别是在Python2和Python3上的Unicode支持方面。
在Linux或OSX上使用freetds-odbc驱动程序和pyodbc是 not 推荐;在这一领域历史上有许多与Unicode相关的问题,包括在Microsoft为Linux和OSX提供ODBC驱动程序之前。既然微软为所有平台提供了驱动程序,为了支持pyodbc,建议使用这些驱动程序。Freetds对于非ODBC驱动程序(如pymsql)仍然是相关的,在这里它工作得很好。
行数支持
pyodbc仅部分支持行数。参见注释 行数支持/ORM版本控制 有关使用ORM版本控制时的重要注意事项。
快速执行器模式
pyodbc驱动程序增加了对“快速执行管理”执行模式的支持,大大减少了dbapi的往返次数。
executemany()
使用Microsoft ODBC驱动程序时调用,用于 适合内存的有限大小批处理 . 通过设置标志来启用该功能.fast_executemany
当要使用ExecuteMany调用时,在DBAPI光标上。当.fast_executemany
标志传递给create_engine()
;请注意,为了使用此标志,ODBC驱动程序必须是Microsoft驱动程序::engine = create_engine( "mssql+pyodbc://scott:tiger@mssql2017:1433/test?driver=ODBC+Driver+13+for+SQL+Server", fast_executemany=True)
警告
pyodbc快速执行模式 缓冲内存中的所有行 并且与非常大的批量数据不兼容。SQLAlchemy的未来版本可能会将此标志作为每次执行选项来支持。
1.3 新版功能.
参见
fast executemany -吉瑟布
Setinputsize支持
pyodbc
cursor.setinputsizes()
如果需要,可以使用方法。要启用此挂接,请传递use_setinputsizes=True
至create_engine()
::engine = create_engine("mssql+pyodbc://...", use_setinputsizes=True)
然后可以自定义挂接的行为,这可能是必要的,特别是在使用fast_ecutemany时,可以通过
DialectEvents.do_setinputsizes()
胡克。有关用法示例,请参阅该方法。在 1.4.1 版更改: pyodbc方言不会使用setinputsize,除非
use_setinputsizes=True
已经过去了。MXODBC
Support for the Microsoft SQL Server database via the mxODBC driver.
DBAPI
Documentation and download information (if applicable) for mxODBC is available at: https://www.egenix.com/
Connecting
Connect String:
mssql+mxodbc://<username>:<password>@<dsnname>
1.4 版后已移除: mxODBC DBAPI已弃用,将在将来的版本中删除。请使用受支持的dbapi之一连接到mssql。
执行模式
mxodbc具有两种类型的语句执行,使用
cursor.execute()
和cursor.executedirect()
方法(第二个方法是DBAPI规范的扩展)。前者使用特定于SQL Server本机客户机ODBC驱动程序sqlDescribeParam的特定API调用,而后者则不使用。显然,当使用sqlDescribeParam时,mxodbc只会重复使用一个准备好的语句。准备好的语句重用的优点之一是性能。缺点是,sqlDescribeParam有一组有限的场景,在这些场景中,可以理解绑定参数,包括不能将它们放在函数调用的参数列表中、FROM之外的任何位置,甚至不能放在FROM子句内的子查询中,这使得在SELECT语句中使用绑定参数对于除了最简单的陈述。
因此,mxodbc方言默认仅对insert、update和delete语句使用“本机”模式,对所有其他语句使用转义字符串模式。
这种行为可以通过
Executable.execution_options()
使用native_odbc_execute
值为的标志True
或False
,其中值为True
将无条件地使用本机绑定参数和值False
将无条件使用字符串转义参数。PysSQL
通过pymssql驱动程序支持Microsoft SQL Server数据库。
连接
Connect String:
mssql+pymssql://<username>:<password>@<freetds_name>/?charset=utf8
pymssql是一个Python模块,提供Python DBAPI接口 FreeTDS 。
注解
pymssql目前不包括在SQLAlchemy的持续集成(CI)测试中。
此驱动程序的现代版本与来自Linux的sqlserver和FreeTDS非常配合,因此强烈推荐使用。但是,pymssql目前没有被维护,并且在支持sqlserver的更新功能方面落后于microsoftobc驱动程序的进度。在编写本文档时,pymssql的最新官方版本是2.1.4版(2018年8月),它不支持:
表值参数(TVP),
datetimeoffset
使用时区感知的列datetime
对象(值以字符串形式发送和检索),以及从预构建的控制盘安装pymssql时,加密连接(例如,到azuresql)。对加密连接的支持需要从源代码构建pymssql,这可能是一个麻烦,尤其是在Windows下。
当使用Microsoft的ODBC Driver for SQL Server(msodbcsql)时,上述功能都受mssql+pyodbc的支持,该驱动程序现在可用于Windows(多种版本)Linux和macOS。