SQL Server使用IDENTITY
结构提供所谓的“自动递增”行为,该结构可放置在整数主键上。SQLAlchemy在Column.autoincrement
中描述的默认“autoincrement”行为内考虑IDENTITY
;这意味着默认情况下,Table
中的第一个整数主键列将被视为标识列,并将生成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(1,1),
x INTEGER NULL,
PRIMARY KEY (id)
)
对于不需要此默认的IDENTITY
生成的情况,请在所有整数主键列上指定autoincrement=False
:
m = MetaData()
t = Table('t', m,
Column('id', Integer, primary_key=True, autoincrement=False),
Column('x', Integer))
m.create_all(engine)
注意
SQL Server禁止引用此类列的显式值的INSERT语句,但SQLAlchemy将在语句执行时检测到此操作并相应地修改IDENTITY_INSERT
标志。由于这不是一个高性能的进程,因此应该小心为实际上不需要IDENTITY行为的列设置autoincrement
标志。
使用schema.Sequence
对象支持对IDENTITY
值参数的特定控制。虽然此对象通常表示支持后端的显式“序列”,但在SQL Server上,它重新用于指定有关标识列的行为,包括对“开始”和“增量”值的支持:
from sqlalchemy import Table, Integer, Sequence, Column
Table('test', metadata,
Column('id', Integer,
Sequence('blah', start=100, increment=10),
primary_key=True),
Column('name', String(20))
).create(some_engine)
会产生:
CREATE TABLE test (
id INTEGER NOT NULL IDENTITY(100,10) PRIMARY KEY,
name VARCHAR(20) NULL,
)
请注意,序列的start
和increment
值是可选的,默认值为1,1。
在INSERT时间处理IDENTITY
列涉及两个关键技术。最常见的是能够为给定的IDENTITY
列获取“最后插入的值”,这是SQLAlchemy在很多情况下隐式执行的过程,最重要的是在ORM中执行。
获取此值的过程有几个变体:
在绝大多数情况下,RETURNING与SQL Server上的INSERT语句一起使用以获取新生成的主键值:
INSERT INTO t (x) OUTPUT inserted.id VALUES (?)
当RETURNING不可用或已通过implicit_returning=False
禁用时,使用scope_identity()
函数或@@identity
变量;行为因后端而异:
when using PyODBC, the phrase ; select scope_identity()
will be appended to the end of the INSERT statement; a second result set will be fetched in order to receive the value. 给定一个表格为:
t = Table('t', m, Column('id', Integer, primary_key=True),
Column('x', Integer),
implicit_returning=False)
INSERT将如下所示:
INSERT INTO t (x) VALUES (?); select scope_identity()
Other dialects such as pymssql will call upon SELECT scope_identity() AS lastrowid
subsequent to an INSERT statement. If the flag use_scope_identity=False
is passed to create_engine()
, the statement SELECT @@identity AS lastrowid
is used instead.
包含IDENTITY
列的表将禁止显式引用标识列的INSERT语句。The SQLAlchemy dialect will detect when an INSERT construct, created using a core insert()
construct (not a plain string SQL), refers to the identity column, and in this case will emit SET IDENTITY_INSERT ON
prior to the insert statement proceeding, and SET IDENTITY_INSERT OFF
subsequent to the execution. 给出这个例子:
m = MetaData()
t = Table('t', m, Column('id', Integer, primary_key=True),
Column('x', Integer))
m.create_all(engine)
engine.execute(t.insert(), {'id': 1, 'x':1}, {'id':2, 'x':2})
上面的列将使用IDENTITY创建,但是我们发出的INSERT语句指定了明确的值。在echo输出中,我们可以看到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
这是适用于测试和批量插入场景的辅助用例。
字符排序规则由基本字符串类型支持,由字符串参数“排序规则”指定:
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
版本0.8中的新功能:字符归类现在是基本字符串类型的一部分。
MSSQL不支持LIMIT或OFFSET关键字。LIMIT通过TOP
Transact SQL关键字直接支持:
select.limit
会产生:
SELECT TOP n
如果使用SQL Server 2005或更高版本,可通过ROW_NUMBER OVER
结构使用支持OFFSET的LIMIT。对于2005以下的版本,使用OFFSET的LIMIT将失败。
All SQL Server dialects support setting of transaction isolation level both via a dialect-specific parameter create_engine.isolation_level
accepted by create_engine()
, as well as the Connection.execution_options.isolation_level
argument as passed to Connection.execution_options()
. 该功能通过发出命令SET TRANSACTION ISOLATION LEVEL tt> < level> / t5>
为每个新的连接。
使用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
的有效值包括:
READ COMMITTED
READ UNCOMMITTED
REPEATABLE READ
SERIALIZABLE
SNAPSHOT
- 特定于SQL Server版本1.1中的新功能:支持Microsoft SQL Server上的隔离级别设置。
MSSQL支持三级列可空性。默认的可空性允许空值,并且在CREATE TABLE结构中是显式的:
name VARCHAR(20) NULL
如果nullable=None
被指定,那么没有指定。换句话说,使用数据库的配置默认值。这将呈现:
name VARCHAR(20)
如果nullable
是True
或False
那么该列将是NULL
或t9> NULL
。
DATE和TIME均受支持。绑定参数按照大多数MSSQL驱动程序的要求转换为datetime.datetime()对象,并根据需要从字符串处理结果。DATE和TIME类型不适用于MSSQL 2005和以前 - 如果检测到2008以下的服务器版本,则这些类型的DDL将作为DATETIME发布。
根据SQL Server 2012/2014 Documentation,NTEXT
,TEXT
和IMAGE
数据类型将从SQL Server在未来的版本中。SQLAlchemy通常将这些类型与UnicodeText
,Text
和LargeBinary
数据类型相关联。
为了适应这种变化,一个新的标志deprecate_large_types
被添加到方言中,如果没有用户设置,它将根据检测到的服务器版本自动设置。此标志的行为如下所示:
当此标志为True
时,UnicodeText
,Text
和LargeBinary
数据类型在用于呈现DDL时,分别是NVARCHAR(max)
,VARCHAR(max)
和VARBINARY(max)
类型。这是添加此标志后的新行为。
当此标志为False
时,UnicodeText
,Text
和LargeBinary
数据类型在渲染DDL时将渲染类型分别为NTEXT
,TEXT
和IMAGE
。这是这些类型的长期行为。
在数据库连接建立之前,该标志以None
值开始。如果方言用于在未设置标志的情况下呈现DDL,则它被解释为与False
相同。
在第一次连接时,方言检测SQL Server版本2012或更高版本是否正在使用;如果标志仍然在None
,则根据是否检测到2012或更高,将其设置为True
或False
。
创建方言时,通常可以通过create_engine()
将标志设置为True
或False
:
eng = create_engine("mssql+pymssql://user:pass@host/db",
deprecate_large_types=True)
通过使用大写类型对象来完全控制所有SQLAlchemy版本是否呈现“旧”或“新”类型:NVARCHAR
,VARCHAR
,types.VARBINARY
,TEXT
,mssql.NTEXT
,mssql.IMAGE
将始终保持固定并始终输出该类型。
版本1.0.0中的新功能
非常旧的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
这种行为模式现在是默认关闭的,因为它似乎没有任何用处;但是在传统应用程序依赖它的情况下,如上所述,它可以使用create_engine()
的legacy_schema_aliasing
参数。
在版本1.1中更改:版本1.0.5中引入的legacy_schema_aliasing
标志允许禁用模式的传统模式现在默认为False。
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
选项现在默认为None,而不是False。mssql_clustered=False
现在显式呈现NONCLUSTERED子句,而None完全忽略CLUSTERED子句,从而允许SQL Server默认设置生效。
除集群之外,MSSQL方言支持Index
的其他特殊选项。
mssql_include
选项为给定的字符串名称呈现INCLUDE(colname):
Index("my_index", table.c.x, mssql_include=['y'])
将使该指数为 创建 T1> INDEX T2> my_index T3> ON T4> 表 T5> (x) INCLUDE (y)
0.8版本中的新功能
索引排序可通过函数表达式获得,例如:
Index("my_index", table.c.x.desc())
would render the index as CREATE INDEX my_index ON table (x DESC)
0.8版本中的新功能
也可以看看
MSSQL支持在数据库级别设置兼容级别的概念。例如,这允许在SQL2005数据库服务器上运行时运行与SQL2000兼容的数据库。server_version_info
will always return the database server version information (in this case SQL2005) and not the compatibility level information. 因此,如果在向后兼容模式下运行,SQAlchemy可能会尝试使用无法由数据库服务器分析的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}
此选项也可以在create_engine()
中使用implicit_returning=False
参数在整个引擎范围内指定。
SQL Server驱动程序具有非常有限的能力来返回从UPDATE或DELETE语句更新的行数。特别是,pymssql驱动程序不支持,而pyodbc驱动程序只能在特定条件下返回此值。
特别是,当使用OUTPUT INSERTED时,更新的rowcount不可用。这会在使用服务器端版本控制方案时影响SQLAlchemy ORM的版本控制功能。在使用pyodbc时,对于使用version_id列与服务器端版本生成器结合使用的任何ORM映射类,需要将“implicit_returning”标志设置为false:
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
}
如果没有上面的implicit_returning标志,那么UPDATE语句将使用OUTPUT inserted.timestamp
,并且rowcount将返回-1,导致版本控制逻辑失败。
不一定特定于SQLAlchemy,SQL Server具有默认的事务隔离模式,可以锁定整个表,甚至可以使并发轻微并发的应用程序长期持有锁和频繁死锁。对于现代级别的并发支持,建议为整个数据库启用快照隔离。这是通过在SQL提示符下执行的以下ALTER DATABASE命令完成的:
ALTER DATABASE MyDatabase SET ALLOW_SNAPSHOT_ISOLATION ON
ALTER DATABASE MyDatabase SET READ_COMMITTED_SNAPSHOT ON
有关SQL Server快照隔离的背景信息,请访问http://msdn.microsoft.com/en-us/library/ms175095.aspx。
IDENTITY
列与所有SQLAlchemy方言一样,所有已知可用于SQL Server的UPPERCASE类型都可以从顶级方言导入,无论它们来源于sqlalchemy.types
还是来自本地方言:
from sqlalchemy.dialects.mssql import \
BIGINT, BINARY, BIT, CHAR, DATE, DATETIME, DATETIME2, \
DATETIMEOFFSET, DECIMAL, FLOAT, IMAGE, INTEGER, MONEY, \
NCHAR, NTEXT, NUMERIC, NVARCHAR, REAL, SMALLDATETIME, \
SMALLINT, SMALLMONEY, SQL_VARIANT, TEXT, TIME, \
TIMESTAMP, TINYINT, UNIQUEIDENTIFIER, VARBINARY, VARCHAR
特定于SQL Server的类型或SQL Server特定的构造参数如下所示:
sqlalchemy.dialects.mssql。
BIT
¶基础:sqlalchemy.types.TypeEngine
__初始化__ T0> ¶ T1>
__init__
属性 object
x .__ init __(...)初始化x;请参阅帮助(类型(x))进行签名
sqlalchemy.dialects.mssql.
CHAR
(length=None, collation=None, convert_unicode=False, unicode_error=None, _warn_on_bytestring=False)¶SQL CHAR类型。
__init__
(length=None, collation=None, convert_unicode=False, unicode_error=None, _warn_on_bytestring=False)¶__init__()
method of String
创建一个字符串保存类型。
参数: |
|
---|
sqlalchemy.dialects.mssql。
DATETIME2
( precision = None, **千瓦 T5> ) T6> ¶ T7>基础:sqlalchemy.dialects.mssql.base._DateTimeBase
,sqlalchemy.types.DateTime
sqlalchemy.dialects.mssql。
DATETIMEOFFSET
( precision = None, ** kwargs T5> ) T6> ¶ T7>sqlalchemy.dialects.mssql.
IMAGE
(length=None)¶基础:sqlalchemy.types.LargeBinary
__初始化__ T0> ( T1> 长度=无 T2> ) T3> ¶ T4>
__init__()
method of LargeBinary
构建一个LargeBinary类型。
参数: | length¶ – optional, a length for the column for use in DDL statements, for those binary types that accept a length, such as the MySQL BLOB type. |
---|
sqlalchemy.dialects.mssql。
MONEY
¶基础:sqlalchemy.types.TypeEngine
__初始化__ T0> ¶ T1>
__init__
属性 object
x .__ init __(...)初始化x;请参阅帮助(类型(x))进行签名
sqlalchemy.dialects.mssql。
NCHAR
( length = None, ** kwargs T5> ) T6> ¶ T7>SQL NCHAR类型。
__ init __
( length = None,** kwargs ) / T5>__init__()
method of Unicode
创建一个Unicode
对象。
参数与String
的参数相同,不同的是convert_unicode
默认为True
。
sqlalchemy.dialects.mssql。
NTEXT
( length = None, ** kwargs T5> ) T6> ¶ T7>基础:sqlalchemy.types.UnicodeText
MSSQL NTEXT类型,用于最多2 ^ 30个字符的可变长度unicode文本。
__ init __
( length = None,** kwargs ) / T5>__init__()
method of UnicodeText
创建一个Unicode转换文本类型。
参数与Text
相同,但convert_unicode
默认为True
。
sqlalchemy.dialects.mssql。
NVARCHAR
( length = None, ** kwargs T5> ) T6> ¶ T7>SQL NVARCHAR类型。
__ init __
( length = None,** kwargs ) / T5>__init__()
method of Unicode
创建一个Unicode
对象。
参数与String
的参数相同,不同的是convert_unicode
默认为True
。
sqlalchemy.dialects.mssql。
REAL
( ** kw ) T5> ¶ T6>sqlalchemy.dialects.mssql。
SMALLDATETIME
( timezone = False ) T5> ¶ T6>基础:sqlalchemy.dialects.mssql.base._DateTimeBase
,sqlalchemy.types.DateTime
__初始化__ T0> ( T1> 时区=假 T2> ) T3> ¶ T4>
DateTime
的 __init__()
构建一个新的DateTime
。
参数: | 时区 ¶ - 布尔值。如果为True,并由后端支持,则会产生'TIMESTAMP WITH TIMEZONE'。对于不支持时区感知时间戳的后端,不起作用。 |
---|
sqlalchemy.dialects.mssql。
SMALLMONEY
¶基础:sqlalchemy.types.TypeEngine
__初始化__ T0> ¶ T1>
__init__
属性 object
x .__ init __(...)初始化x;请参阅帮助(类型(x))进行签名
sqlalchemy.dialects.mssql。
SQL_VARIANT
¶基础:sqlalchemy.types.TypeEngine
__初始化__ T0> ¶ T1>
__init__
属性 object
x .__ init __(...)初始化x;请参阅帮助(类型(x))进行签名
sqlalchemy.dialects.mssql.
TEXT
(length=None, collation=None, convert_unicode=False, unicode_error=None, _warn_on_bytestring=False)¶SQL TEXT类型。
__init__
(length=None, collation=None, convert_unicode=False, unicode_error=None, _warn_on_bytestring=False)¶__init__()
method of String
创建一个字符串保存类型。
参数: |
|
---|
sqlalchemy.dialects.mssql。
TIME
( precision = None, ** kwargs T5> ) T6> ¶ T7>sqlalchemy.dialects.mssql。
TINYINT
¶ __初始化__ T0> ¶ T1>
__init__
属性 object
x .__ init __(...)初始化x;请参阅帮助(类型(x))进行签名
sqlalchemy.dialects.mssql。
UNIQUEIDENTIFIER
¶基础:sqlalchemy.types.TypeEngine
__初始化__ T0> ¶ T1>
__init__
属性 object
x .__ init __(...)初始化x;请参阅帮助(类型(x))进行签名
sqlalchemy.dialects.mssql.
VARCHAR
(length=None, collation=None, convert_unicode=False, unicode_error=None, _warn_on_bytestring=False)¶SQL VARCHAR类型。
__init__
(length=None, collation=None, convert_unicode=False, unicode_error=None, _warn_on_bytestring=False)¶__init__()
method of String
创建一个字符串保存类型。
参数: |
|
---|
通过PyODBC驱动程序支持Microsoft SQL Server数据库。
PyODBC的文档和下载信息(如果适用)可在以下网址获得:http://pypi.python.org/pypi/pyodbc/
此处的URL将被转换为PyODBC连接字符串,详见ConnectionStrings。
A DSN-based connection is preferred overall when using ODBC. 基本的基于DSN的连接如下所示:
engine = create_engine("mssql+pyodbc://scott:tiger@some_dsn")
上面哪个,将下面的连接字符串传递给PyODBC:
dsn=mydsn;UID=user;PWD=pass
如果省略用户名和密码,则DSN表格还会将Trusted_Connection=yes
指令添加到ODBC字符串中。
基于主机名的连接不是首选,但是受支持。ODBC驱动程序名称必须明确指定:
engine = create_engine("mssql+pyodbc://scott:tiger@myhost:port/databasename?driver=SQL+Server+Native+Client+10.0")
版本1.0.0中已更改:现在,基于主机名的PyODBC连接需要明确指定的SQL Server驱动程序名称。由于SQLAlchemy根据平台和安装的驱动程序而有所不同,SQLAlchemy无法选择最佳默认值。
由Pyodbc方言解释的其他关键字在DSN和主机名情况下都被传递给pyodbc.connect()
包括:odbc_autotranslate
,ansi
, unicode_results
,autocommit
。
PyODBC连接字符串也可以使用参数odbc_connect
完全按照ConnectionStrings中的规定发送到驱动程序中。但是,使用urllib.quote_plus
时,定界符必须是URL转义的:
import urllib
params = urllib.quote_plus("DRIVER={SQL Server Native Client 10.0};SERVER=dagger;DATABASE=test;UID=user;PWD=password")
engine = create_engine("mssql+pyodbc:///?odbc_connect=%s" % params)
关于unicode,PyTBC在FreeTDS和/或EasySoft后端的当前状态很差;不同操作系统平台和版本的UnixODBC与IODBC与FreeTDS / EasySoft相比,PyODBC本身会显着改变字符串的接收方式。PyODBC方言尝试使用它所知道的所有信息来确定是否可以将Python unicode文字直接传递给PyODBC驱动程序;虽然SQLAlchemy可以首先将它们编码为字节串,但有些用户报告说PyODBC对某些编码的字节串错误处理,并且需要一个Python unicode对象,而作者观察到python unicode完全被PyODBC误解的普遍情况,特别是在处理表反射中使用的信息模式表,并且必须首先将该值编码为字符串。
正是由于这个原因,可以使用supports_unicode_binds
参数控制create_engine()
来控制是否将绑定参数的unicode文字发送到PyODBC。当默认值为None
时,PyODBC方言将使用最佳猜测来判断驱动程序是否处理unicode字面值。当False
时,unicode文字将首先被编码,并且True
unicode文字将被直接传递。这是一个临时标志,当unix + PyODBC的unicode情况稳定时,希望不需要该标志。
New in version 0.7.7: supports_unicode_binds
parameter to create_engine()
.
Pyodbc只支持rowcount。在使用ORM版本控制时,请参阅Rowcount Support / ORM Versioning中的说明以了解重要说明。
通过mxODBC驱动程序支持Microsoft SQL Server数据库。
mxODBC的文档和下载信息(如果适用)可在以下网址获得:http://www.egenix.com/
mxODBC使用cursor.execute()
和cursor.executedirect()
方法(第二种是DBAPI规范的扩展)提供了两种语句执行风格。前者使用特定于SQL Server Native Client ODBC驱动程序的特定API调用(已知SQLDescribeParam),而后者则不使用。
当使用SQLDescribeParam时,mxODBC显然只会重复使用单个预准备语句。准备语句重用的好处是性能。缺点是SQLDescribeParam的绑定参数被理解为有限的一组场景,包括它们不能放在函数调用的参数列表中,在FROM之外的任何地方,或者甚至在FROM子句内的子查询中 - 使得在SELECT语句中绑定参数是不可能的,除了最简单的陈述之外。
因此,默认情况下,mxODBC方言默认只使用INSERT,UPDATE和DELETE语句的“本机”模式,对所有其他语句使用转义字符串模式。
This behavior can be controlled via execution_options()
using the native_odbc_execute
flag with a value of True
or False
, where a value of True
will unconditionally use native bind parameters and a value of False
will unconditionally use string-escaped parameters.
通过pymssql驱动程序支持Microsoft SQL Server数据库。
pymssql的文档和下载信息(如果适用)可在以下网址获得:http://pymssql.org/
pymssql是一个Python模块,它提供围绕FreeTDS的Python DBAPI接口。兼容版本适用于Linux,MacOSX和Windows平台。
通过zxJDBC为Jython驱动程序支持Microsoft SQL Server数据库。
注意
当前版本的SQLAlchemy不支持Jython。zxjdbc方言应该被认为是实验性的。
此数据库的驱动程序可在以下网站获得:http://jtds.sourceforge.net/
通过adodbapi驱动程序支持Microsoft SQL Server数据库。
有关adodbapi的文档和下载信息(如果适用),请访问:http://adodbapi.sourceforge.net/
注意
adodbapi方言目前尚未实现SQLAlchemy 0.6及更高版本。