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 COMMITTEDREAD UNCOMMITTEDREPEATABLE READSERIALIZABLESNAPSHOT - 特定于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__ 属性 objectx .__ 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__ 属性 objectx .__ 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__ 属性 objectx .__ init __(...)初始化x;请参阅帮助(类型(x))进行签名
sqlalchemy.dialects.mssql。 SQL_VARIANT ¶基础:sqlalchemy.types.TypeEngine
__初始化__ T0> ¶ T1>__init__ 属性 objectx .__ 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__ 属性 objectx .__ init __(...)初始化x;请参阅帮助(类型(x))进行签名
sqlalchemy.dialects.mssql。 UNIQUEIDENTIFIER ¶基础:sqlalchemy.types.TypeEngine
__初始化__ T0> ¶ T1>__init__ 属性 objectx .__ 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及更高版本。