WEB开发网
开发学院数据库MSSQL Server SQL Server 2000分布式查询:OLE DB连接 阅读

SQL Server 2000分布式查询:OLE DB连接

 2006-12-30 09:17:03 来源:WEB开发网   
核心提示:概述和术语 在 MicrosoftSQL Server 2000 中,分布式查询允许SQL Server用户访问基于SQL Server的服务器以外的数据(位于其他运行SQL Server的服务器或是具有OLE DB接口的其他数据源中),SQL Server 2000分布式查询:OLE DB连接,OLE DB提供了统一

概述和术语

在 MicrosoftSQL Server 2000 中,分布式查询允许SQL Server用户访问基于SQL Server的服务器以外的数据(位于其他运行SQL Server的服务器或是具有OLE DB接口的其他数据源中)。OLE DB提供了统一的方式来访问异类数据源中的列表数据。

在本文中,分布式查询是指任何引用了一个或多个外部OLE DB数据源中表或行集的SELECT、INSERT、UPDATE或DELETE语句。

远程表是指存储于 OLE DB 数据源中并且不在执行查询的SQL Server 所在服务器上的表。一个分布式查询可以访问一个或多个远程表。

OLE DB提供程序类别

根据OLE DB提供程序在SQL Server的分布式查询中的功能,我们将它们划分为如下类别。根据定义,它们并非互相排斥;某种提供程序可能属于一个或多个类别:

SQL 命令提供程序

索引提供程序

简单表提供程序

非SQL 命令提供程序

SQL 命令提供程序

凡是以SQL标准语法(SQL Server 认可)支持 Command对象的提供程序,都属于此类别。下面是 OLE DB 提供程序被SQL Server 视为SQL 命令提供程序的必要条件:

提供程序必须支持 Command 对象及其所有强制 OLE DB 接口:ICommand、ICommandText、IColumnsInfo、ICommandProperties 和 IAccessor。

提供程序支持的SQL 语法必须至少是SQL 子集。提供程序必须通过 DBPROP_SQLSUPPORT 属性来报告语法。

SQL 命令提供程序的示例为:Microsoft OLE DB Provider forSQL Server 和 Microsoft OLE DB Provider for ODBC。

索引提供程序

索引提供程序支持并提供与OLE DB对应的索引,同时还允许基于索引对基本表执行查找。下面是 OLE DB 提供程序被SQL Server 视为索引提供程序的必要条件:

提供程序必须以 TABLES、COLUMNS 和 INDEXES 架构行集支持 IDBSchemaRowset 接口。

提供程序必须支持通过 IOpenRowset 打开索引中的行集(通过指定索引名和相应的基本表名称)。

Index 对象必须支持其所有的强制接口:IRowset、IRowsetIndex、IAccessor、IColumnsInfo、IRowsetInfo 和 IConvertTypes。

对带索引基本表打开的行集(通过使用 IOpenRowset)必须支持 IRowsetLocate 接口,以便根据书签在行上定位。

如果一个OLE DB提供程序满足以上条件,用户可以设置提供程序选项 Index As Access Path,以允许SQL Server 使用提供程序的索引来执行查询。默认情况下,除非该选项已被设置,否则SQL Server 不会尝试使用提供程序的索引。

注意:SQL Server支持多个影响SQL Server访问OLE DB提供程序的方法的选项。可以使用SQL Server 企业管理器中的“链接服务器属性”对话框来设置这些选项。

简单表提供程序

简单表提供程序通过IOpenRowset接口来表现根据基本表打开行集的方式。这些提供程序既不是SQL 命令提供程序也不是索引提供程序;而是SQL Server 分布式查询所能处理的提供程序中最简单的一类。

对于此类提供程序,SQL Server 仅能在分布式查询运行过程执行表扫描操作。

非SQL 命令提供程序

该类提供程序支持 Command对象及其所有强制接口,但不支持SQL Server 认可的SQL 标准语法。

非SQL 命令提供程序的两个示例是:Microsoft OLE DB Provider for Indexing Service 和 Microsoft Windows NT®Active Directory™Service Interfaces (ADSI) OLE DB Provider。

Transact-SQL 子集

如果提供程序支持所需的 OLE DB 接口,下列 Transact-SQL 语句类别都可以用于分布式查询。

除了将远程表作为目的表的 SELECT INTO 语句外,其他所有的 SELECT 语句都可以使用。

如果提供程序支持插入操作所需的接口,INSERT 语句可以用于远程表。有关 INSERT 语句的 OLE DB 要求的详细信息,请查阅本文后面的INSERT语句。

如果提供程序满足 OLE DB 接口在特定表上的要求,UPDATE 和 DELETE 语句也可以用于远程表。有关更新或删除远程表时 OLE DB 接口必须满足的要求和条件,请参阅本文后面的UPDATE和DELETE。

游标支持

如果提供程序支持所需的 OLE DB 功能,则分布式查询支持快照和键集两种游标。分布式查询不支持动态游标。用户请求的分布式查询的动态游标将自动降级为键集游标。

快照游标在游标打开时被写入,而且结果集保持不变;对基本表的更新、插入和删除操作不会反映到游标中。

键集游标在游标打开时被写入,而且结果集在游标的整个生存期中保持不变。但是,如果更新或删除基本表中的行,当访问这些行时,能够在游标中看到变化。如果对基本表的插入操作可能影响游标成员,则这种变化则是不可见的。

如果提供程序满足更新和删除远程表的条件,则可以通过使用分布式查询中定义的游标以及对远程表的引用来更新和删除远程表,例如:table UPDATE | DELETE <远程表> WHERE CURRENT OF <游标名称>。有关详细信息,请参阅本文后面的UPDATE和DELETE 语句。

支持键集游标的要求

如果满足所有 Transact-SQL 语法的条件,而且满足以下两种情况之一,那么在分布式查询中就支持键集游标:

在查询中,OLE DB 提供程序支持所有远程表上的可重用书签。可重用书签可以从给定表的某个行集中隐去,然后用于同一表中的其他行集上。对可重用书签的支持是通过 IDBSchemaRowset 的 TABLES_INFO 架构行集来指定的,方法是将 BOOKMARK_DURABILITY 列设置为 BMK_DURABILITY_INTRANSACTION 或某种更高的持久性。

所有的远程表都通过 IDBSchemaRowset 接口的 INDEXES 行集来列出唯一键。应该存在一个索引项,其中的 UNIQUE 列设置为 VARIANT_TRUE。

包含OpenQuery 函数的分布式查询不支持键集游标。

支持可更新键集游标的要求

通过在分布式查询上定义的键集游标,可以更新或删除远程表,例如:UPDATE | DELETE< 远程表>WHERE CURRENT OF <游标名称>。下面是在分布式查询中允许使用可更新游标的条件:

如果提供程序也满足对远程表进行更新和删除操作的条件,就允许使用可更新游标。有关详细信息,请参阅本文后面的UPDATE 和 DELETE 语句。

所有的可更新键集游标操作必须位于使用可复读或更高的隔离级别的用户定义事务中。此外,提供程序必须以 ITransactionJoin 接口支持分布式事务处理。

OLE DB 提供程序交互阶段

所有分布式查询的执行方案都有六种操作:

建立连接和检索属性操作,指定SQL Server 连接 OLE DB 提供程序的方法以及将用到提供程序的哪些属性。

表名解析和检索元数据操作,指定SQL Server 将远程表名称(指定时使用两种方法之一:基于链接服务器的名称或特殊名称)解析为提供程序中相应数据对象的方法。这也包括SQL Server 为编译和优化分布式查询从提供程序检索的表元数据。

事务管理操作,指定所有与 OLE DB 提供程序的事务相关的交互。

数据类型处理操作,该操作指定在执行分布式查询过程中,当SQL Server从OLE DB提供程序获得数据或向其导出数据时SQL Server 处理 OLE DB 数据类型的方法。

错误处理操作,指定SQL Server 使用从提供程序获得的扩展错误信息的方法。

安全性操作,指定SQL Server 安全性和提供程序安全性的交互方式。

建立连接和检索属性

SQL Server 使用 OPENROWSET 功能支持两种远程数据对象命名协议:基于链接服务器的四段式名称和特殊名称。

基于链接服务器的名称

链接服务器是对OLE DB数据源的抽象。基于链接服务器的名称分为四段:<链接服务器>.<目录>.<架构>.<对象>,其中<链接服务器>是链接服务器的名称。SQL Server 将<链接服务器>视为OLE DB提供程序和连接属性(用于向提供程序标识数据源)的来源。其他三个名称段被OLE DB数据源解释为对特定远程表的标识。

特殊名称

特殊名称是基于 OPENROWSET 或 OPENDATASOURCE 函数的名称。它包括在分布式查询中每次引用远程表时的所有连接信息(包括所使用的 OLE DB 提供程序、用于标识数据源的属性、用户 ID 和密码)。

默认情况下,只允许系统管理员使用特殊名称。要使用基于 OLE DB 提供程序的特殊名称,应将提供程序的 DisallowAdhocAccess 选项设置为 0。

如果使用链接服务器名称,SQL Server 将在链接服务器定义中为 OLE DB 提供程序提取提供程序的名称和初始化属性。如果使用特殊名称,SQL Server 将从 OPENROWSET 函数的参数中提取相同的信息。

有关使用四段式名称建立链接服务器和基于特殊名称的语法的详细说明,请参阅SQL Server Books Online。

连接 OLE DB 提供程序

以下是SQL Server连接OLE DB提供程序时执行的高级步骤。

SQL Server 创建数据源对象。SQL Server使用提供程序的ProgID来建立数据源对象(DSO)的实例。ProgID被指定为链接服务器配置信息的 provider_name 参数,或在使用特殊名称时被指定为 OPENROWSET 函数的第一个参数。 SQL Server 通过 OLE DB 服务组件接口 IDataInitialize 创建提供程序的 DSO 实例。这使服务组件管理器可以在提供程序的本地功能上集成其服务(例如回滚和支持更新)。另外,通过 IDataInitialize 建立提供程序的实例还允许 OLE DB 服务组件为它们提供连接池,这样可减少连接和初始化的开销。

在SQL Server 的进程中还是在一个独立的进程中创建给定提供程序的实例,可以根据需要进行配置。在独立的进程中创建实例能够保护SQL Server 进程免受提供程序故障的影响。但同时还存在着与在SQL Server 进程外组织 OLE DB 调用有关的性能开销。通过设置提供程序选项 Allow In Process,可以将提供程序配置为进程内实例或进程外实例。有关设置提供程序选项的详细信息,请参阅SQL Server Books Online。要学习更多有关 OLE DB 服务组件和建立会话池的知识,请参阅提供程序的 OLE DB 文档。 初始化数据源。

创建 DSO 之后,如果服务器的配置选项remotelogin timeout 大于 0,IDBProperties 接口将设置 DBPROP_INIT_TIMEOUT 初始化属性;该属性为必需的属性。

如果在链接服务器定义或 OPENROWSET 函数的第二个参数中指定或隐含了下列属性,则它们将被设置:

DBPROP_INIT_PROVIDERSTRING

DBPROP_INIT_DATASOURCE

DBPROP_INIT_LOCATION

DBPROP_INIT_CATALOG

DBPROP_AUTH_USERID

DBPROP_AUTH_PASSWORD 设置了这些属性后,将调用 IDBInitialize::Initialize 以指定的属性初始化 DSO。 SQL Server 收集特定提供程序的信息。

SQL Server 将收集若干用于分布式查询执行中的提供程序属性;这些属性将通过调用IDBProperties::GetProperties 来检索。这些属性全都是可选的;但是,对所有相关属性的支持将允许SQL Server 充分利用提供程序的功能。例如,在确定SQL Server 是否能够向提供程序发送查询时,需要使用DBPROP_SQLSUPPORT。如果提供程序不支持该属性,SQL Server就不能将远程提供程序用作SQL命令提供程序,即使它是一个SQL命令提供程序。在下表(表 1)中,“默认值”列列出了在提供程序不支持该属性时SQL Server 所采用的值。

表 1:SQL Server OLE-DB 提供程序采用的属性

属性默认值用法
DBPROP_DBMSNAME用于错误信息。
DBPROP_DBMSVER用于错误信息。
DBPROP_PROVIDERNAME用于错误信息。
DBPROP_PROVIDEROLEDBVER1.5用于确定 2.0 功能的可用性。
DBPROP_CONCATNULLBEHAVIOR用于确定提供程序的 NULL 连接行为是否与SQL Server 一致。
DBPROP_NULLCOLLATION只有在 NULLCOLLATION 符合SQL Server 的 Null 排序规则时才允许排序/使用索引。
DBPROP_OLEOBJECTS确定提供程序是否支持大数据对象列的结构化存储接口。
DBPROP_STRUCTUREDSTORAGE确定支持哪种用于大对象类型的结构化存储接口( ILockBytes、Istream 和 ISequentialStream 三种接口之一)。
DBPROP_MULTIPLESTORAGEOBJECTSFalse确定是否支持同时打开一个以上的大对象列。
DBPROP_SQLSUPPORT确定是否能够向提供程序发送SQL 查询。
DBPROP_CATALOGLOCATIONDBPROPVAL_CL_START用于构造多段表名。
SQLPROP_DYNAMICSQLFalseSQL Server 特有的属性:如果返回 VARIANT_TRUE,则指示参数标记 '?' 可以用于参数化查询执行。
SQLPROP_NESTEDQUERIESFalseSQL Server 特有的属性:如果返回 VARIANT_TRUE,则指示提供程序在 FROM 子句中支持嵌套的 SELECT 语句。
SQLPROP_GROUPBYFalseSQL Server 特有的属性:如果返回 VARIANT_TRUE,则指示提供程序支持在 SELECT 语句中使用 GROUP BY 子句(如SQL-92 标准所规定的一样)。
SQLPROP_DATELITERALSFalseSQL Server 特有的属性:如果返回 VARIANT_TRUE,则指示提供程序支持各SQL Server Transact-SQL 语法所规定的日期时间文字。
SQLPROP_ANSILIKEFalseSQL Server 特有的属性:该属性对支持SQL-Minimum 级别的提供程序比较有意义,并且它支持各SQL-92 entry 级别所规定的 LIKE 运算符(使用 '%' 和 '_' 作为通配符)。
SQLPROP_SUBQUERIESFalseSQL Server 属性:该属性对支持SQL-Minimum 级别的提供程序比较有意义。它指示提供程序支持SQL-92 Entry 级别所规定的子查询。包括 SELECT 序列和 WHERE 子句中的子查询(支持相关子查询以及 IN、EXISTS、ALL 和 ANY 运算符)。
SQLPROP_INNERJOINFalseSSQL Server 特有的属性:该属性对支持SQL-Minimum 级别的提供程序比较有意义。它指示支持在 FROM 子句中使用多表的联接。

下面是从 IDBInfo::GetLiteralInfo 检索到的三个文字:DBLITERAL_CATALOG_SEPARATOR、DBLITERAL_SCHEMA_SEPARATOR(用于根据给定的目录、架构和对象名构造完整的对象名称)和 DBLITERAL_QUOTE(用于引用发送到提供程序的SQL 查询中的标识符名称)。

如果提供程序不支持分隔符文字,SQL Server 将使用句点 (.) 作为默认的分隔符字符。如果提供程序只支持目录分隔符字符而不支持架构分隔符字符,则SQL Server 将把目录分隔符字符也作为架构分隔符字符使用。如果提供程序不支持 DBLITERAL_QUOTE,SQL Server 将使用单引号 (') 作为引用字符。

注意: 如果提供程序的名称分隔符文字和这些默认值不匹配,提供程序必须使用 IDBInfo 将它们公开,以便SQL Server 通过四段式名称访问它的表。如果没有将这些文字公开,那么对于这样的提供程序将只能使用传递查询。

表名解析和元数据检索

SQL Server 将分布式查询中给定的远程表名称解析为 OLE DB 数据源中的特定表或视图。基于链接服务器的和特殊的命名架构都将导致提供程序将名称解释为三段式名称。在使用基于链接服务器的名称时,四段式名称的后三部分形成目录、架构和对象名。在使用特殊名称时,OPENROWSET 函数的第三个参数指定了说明目录、架构和对象名的三段式名称。目录和架构名称中可以有一个为空值或全部为空值。(当目录名和架构名为空时,四段式名称将变成:<服务器名称>...<对象名称>。)在此情况下,SQL Server 搜索架构行集表时将使用 NULL 作为对应的值。

SQL Server 使用的名称解析规则和元数据检索的步骤取决于提供程序是否支持Session 对象的IDBSchemaRowset接口。

如果支持IDBSchemaRowset ,则使用IDBSchemaRowset 接口中的TABLES、COLUMNS、INDEXES和TABLES_INFO架构行集。(TABLES_INFO 架构行集在 OLE DB 2.0 中定义。)SQL Server通过限制IDBSchemaRowset接口返回的架构行集来寻找与特定远程表名称部分匹配的架构行。下面是与提供程序支持的架构行集限制有关的规则,以及SQL Server 使用这些规则来检索远程表元数据的方法:

对 TABLE_NAME 和 COLUMN_NAME 列的限制总是必要的。

如果提供程序支持对 TABLE_CATALOG(或 TABLE_SCHEMA)的限制,SQLServer 将使用对 TABLE_CATALOG(或 TABLE_SCHEMA)的限制。如果在远程表名中没有指定目录(或架构)名称,则使用 NULL 值作为相应的限制值。如果指定了目录(或架构)名称,提供程序必须支持对 TABLE_CATALOG(或 TABLE_SCHEMA)的相应限制。

提供程序必须全部支持对 TABLES 和 COLUMNS 中的 TABLE_SCHEMA 列的限制,或者全部不支持。提供程序必须全部支持对 TABLES 和 COLUMNS 的目录名称限制,或者全部不支持。

如果支持 INDEXES 上的任何限制,提供程序必须全部支持对 TABLES 和 INDEXES 的架构限制,或者全部不支持。提供程序必须全部支持对 TABLES 和 INDEXES 行集的目录名限制,或者全部不支持。

从TABLES架构行集中,通过按上述规则设置限制,SQL Server可检索TABLE_CATALOG、TABLE_SCHEMA、TABLE_NAME、TABLE_TYPE 和 TABLE_GUID 列。

从COLUMNS 架构行集中,SQL Server可检索TABLE_CATALOG、TABLE_SCHEMA、TABLE_NAME、COLUMN_NAME、COLUMN_GUID、ORDINAL_POSITION、COLUMN_FLAGS、IS_NULLABLE、DATA_TYPE、TYPE_GUID、CHARACTER_MAXIMUM_LENGTH、NUMERIC_PRECISION 和 NUMERIC_SCALE 列。COLUMN_NAME、DATA_TYPE 和 ORDINAL_POSITION 必须返回有效的非空值。如果 DATA_TYPE 是 DBTYPE_NUMERIC 或 DBTYPE_DECIMAL,相应的 NUMERIC_PRECISION 和 NUMERIC_SCALE 也必须是有效的非空值。

从可选的 INDEXES 架构行集中,通过按原先规则设置限制,SQL Server 可在指定的远程表上寻找索引。SQL Server 从找到的索引条目中检索 TABLE_CATALOG、TABLE_SCHEMA、TABLE_NAME、INDEX_CATALOG、INDEX_SCHEMA、INDEX_NAME、PRIMARY_KEY、UNIQUE、CLUSTERED、FILL_FACTOR、ORDINAL_POSITION、COLUMN_NAME、COLLATION、CARDINALITY 和 PAGES 列。

从可选的 TABLES_INFO 行集中,SQL Server 寻找有关指定远程表的附加信息(例如书签支持、书签类型和长度)。除了 TABLES_INFO 行集中的 DESCRIPTION 列以外,所有的列都被使用。TABLES_INFO 行集中的信息按如下要求使用:

BOOKMARK_DURABILITY 列用于实现更有效的键集游标。如果该列的值为 BMK_DURABILITY_INTRANSACTION 或更高持久性的值,SQL Server 在实现键集游标时,将对远程表行使用基于书签的检索和更新。

BOOKMARK_TYPE、BOOKMARK_DATA TYPE 和 BOOKMARK_MAXIMUM_LENGTH 列用于在编译查询时确定书签的元数据。如果这些列不被支持,SQL Server 将在编译时通过 IOpenRowset 打开基本表行集来获得书签信息。

如果不支持IDBSchemaRowset并且远程表名称包含了目录或架构名,则SQL Server 将要求IDBSchemaRowset并返回一个错误。但是,如果既没有提供目录名,也没有提供架构名,SQL Server将打开对应于远程表的行集,并从行集对象的强制接口IColumnsInfo中检索列元数据。

SQL Server 通过调用IOpenRowset::OpenRowset打开对应于表的行集。提供OPENROWSET 的表名是由目录、架构和对象名等部分构成的。

名称的每个部分(目录、架构、对象名)都使用提供程序的引用符 (DBLITERAL_QUOTE) 引用,然后使用 DBLITERAL_CATALOG_SEPARATOR 字符和 DBLITERAL_SCHEMA_SEPARATOR 字符连接到一起。名称的构造遵循 IOpenRowset 中的 OLE DB 规则。

在行集对象打开后,可通过 IColumnsInfo::GetColumnInfo 检索表中的列元数据。

如果IDBSchemaRowset不支持TABLES、COLUMNS 和 TABLES_INFO行集,SQL Server将打开两次基本表上的行集:在查询编译时打开一次来检索元数据,在查询运行时再打开一次。由于打开行集而受影响的提供程序(例如,运行更改实时设备状态的代码,发送电子邮件,运行任意用户提供的代码)必须注意这种行为。

检索统计信息

如果提供程序支持基本表上的分布式统计,那么SQL Server 2000将使用这些统计。有两种统计可用于SQL Server查询处理器:

列(或元组)基数:它是在一个表的列(或一组列)中唯一值的数目。可用于依据列评估谓词的选择性。支持分布式统计的提供程序必须支持至少一种基数。

柱状图:如果值的分布不均匀,则唯一值的数目对于评估谓词的选择性是不够充分的。在此情况下,提供一个柱状图即可就表中列值的分布提供更好的图形化信息。 有了统计就能使SQL Server查询优化程序更好地评估一个查询中的中间操作的基数,这将使它生成更好的执行方案。

OLE DB 提供程序应支持以下分布式统计: 强制:支持属性 (1) DBPROP_TABLESTATISTICS,该属性指示是否支持列或元组基数以及是否支持柱状图;和属性 (2) DBPROP_OPENROWSETSUPPORT,该属性使用 DBPROPVAL_ORS_HISTOGRAM 位来指示是否支持柱状图。

强制:TABLE_STATISTICS 架构行集。TABLE_STATISTICS 架构行集列出了给定数据库中可用的统计。它也包含了架构行集本身的列或元组基数,同时指示了特定列是否支持柱状图。为了使SQL Server 能够使用统计,此架构行集中的 TABLE_NAME、STATISTICS_NAME、STATISTICS_TYPE、COLUMN_NAME 和 ORDINAL_POSITION 列是强制的。COLUMN_CARDINALITY 或 TUPLE_CARDINALITY 中至少有一个是强制的。如果支持柱状图,则 NO_OF_RANGES 也是强制的。

可选:可选地,如果提供程序支持柱状图,它应支持 IOpenRowset::OpenRowset 方法的增强功能(允许通过指定相应统计的 DBID 来打开一个柱状图行集)。

约束

如果OLE DB提供程序支持OLE DB 2.6的新架构行集CHECK_CONSTRAINTS_BY_TABLE,SQL Server 2000查询优化程序也可以使用远程数据源中基本表上的 CHECK 约束。架构行集的 CHECK_CLAUSE 列将返回符合SQL-92 语法的 CHECK 子句谓词。查询优化程序使用约束信息来消除或简化因表中约束的存在而总为真或总为假的谓词。

事务管理

SQL Server 通过使用提供程序的ITransactionLocal(用于本地事务)和ITransactionJoin(用于分布式事务)OLE DB 接口支持以事务方式访问分布式数据。通过启动提供程序的本地事务,SQL Server可保证单元写操作。通过使用分布式事务,SQL Server可确保包括多个节点的事务在所有节点中都有同样的结果(无论是提交还是终止)。如果提供程序不支持必要的 OLE DB 事务相关接口,根据本地事务的环境将不允许针对该提供程序进行更新操作。

下表(表2)描述了在用户执行分布式查询(给定了提供程序的功能和本地事务的环境)时发生的事情。针对提供程序的读操作是指一条 SELECT 语句,或者指远程表用在 SELECT INTO、INSERT、UPDATE 或 DELETE 语句的输入端的情形。针对提供程序的写操作是指 INSERT、UPDATE 或 DELETE 语句,其中远程表作为目的表。

表2:基于提供程序的功能和事务环境的分布式查询结果。

分布式查询

发生

提供程序不

支持

ITransactionLocal

提供程序同时支持

ItransactionLocal

但不支持

ITransactionJoin

提供程序同时支持

ItransactionLocal

ITransactionJoin

在自身事务中(非用户事务)。默认情况下,只允许读操作。如果启用提供程序级选项 Nontransacted Updates,则允许写操作。(当启用该选项时,SQL Server不能保证提供程序数据的原子性和一致性。这将导致写操作的影响部分地反映到远程数据源中,而且无法撤消。)所有语句都允许在远程数据上运行。键集游标是只读的。

本地事务在提供程序上以当前SQL Server 会话隔离级别启动,然后在语句运行成功后提交。(除非使用 SET TRANSACTION ISOLATION LEVEL 对SQL Server 会话的隔离级别进行修改,否则默认级别是 READ COMMITTED。提供程序必须支持请求的隔离级别。)

允许所有语句。键集游标是只读的。

本地事务在提供程序上以当前SQL Server 会话隔离级别启动,然后在语句运行成功后提交。

在用户事务中(也就是说,发生在BEGIN TRAN 或 BEGIN DISTRIBUTED TRAN和COMMIT之间)。如果事务的隔离级别是READ COMMITTED(默认值)或更低,则允许读操作。如果隔离级别更高,将不允许分布式查询。只允许读操作。新的分布式事务在提供程序上以当前SQL Server 会话隔离级别启动。允许所有语句。

新的分布式事务在提供程序上以当前SQL Server 会话隔离级别启动,然后在用户事务提交时提交。对于修改数据的语句,默认情况下,SQL Server 将在分布式事务下启动一个嵌套的事务,这样出现某种错误时就可以停止修改数据语句,而不必停止周围的事务。如果 XACT_ABORT SET 选项为打开状态,SQL Server 就不需要嵌套事务支持,而且在修改数据的语句出错时可停止周围的事务。

分布式查询中数据类型的处理

OLE DB 提供程序按照由OLE DB 定义的数据类型(由 OLE DB 的 DBTYPE 指示)表明它们的数据。SQL Server 在服务器中以本地的SQL Server 类型处理外部数据;不管数据是被SQL Server 使用还是从SQL Server 导出,这种处理方式都会产生从 OLE DB 数据类型到SQL Server 本地数据类型的映射(见表 3)或者从SQL Server 本地数据类型到 OLE DB 数据类型的映射。这种映射是以隐含方式实现的,除非另外注明。

分布式查询中的数据类型使用下列两种映射方式之一进行处理:

使用端映射,当远程表出现在 SELECT 语句中并位于 INSERT、UPDATE 和 DELETE 语句的输入端时,该映射在使用端将类型从 OLE DB 数据类型映射为SQL Server 本地数据类型。

导出端映射,当远程表作为 INSERT 或 UPDATE 语句的目的表出现时,该映射在导出端将类型从SQL Server 数据类型映射为 OLE DB 数据类型。

表 3:SQL Server 和 OLE-DB 数据类型映射表。

OLE DB 类型DBCOLUMNFLAGSQL Server 数据类型
DBTYPE_I1*numeric(3,0)
DBTYPE_I2smallint
DBTYPE_I4int
DBTYPE_I8numeric(19,0)
DBTYPE_UI1tinyint
DBTYPE_UI2*numeric(5,0)
DBTYPE_UI4*numeric(10,0)
DBTYPE_UI8*numeric(20,0)
DBTYPE_R4float
DBTYPE_R8real
DBTYPE_NUMERICnumeric
DBTYPE_DECIMALdecimal
DBTYPE_CYmoney
DBTYPE_BSTRDBCOLUMNFLAGS_ISFIXEDLENGTH=true

或最大长度大于 4000 个字符

ntext
DBTYPE_BSTRDBCOLUMNFLAGS_ISFIXEDLENGTH=truenchar
DBTYPE_BSTRDBCOLUMNFLAGS_ISFIXEDLENGTH=falsenvarchar
DBTYPE_IDISPATCHError
DBTYPE_ERRORError
DBTYPE_BOOLbit
DBTYPE_VARIANT*nvarchar
DBTYPE_IUNKNOWNError
DBTYPE_GUIDuniqueidentifier
DBTYPE_BYTESDBCOLUMNFLAGS_ISLONG=true 或最大长度大于 8000image
DBTYPE_BYTESDBCOLUMNFLAGS_ISROWVER=true,

DBCOLUMNFLAGS_ISFIXEDLENGTH=true、

列大小等于 8 或未报告最大长度。

timestamp
DBTYPE_BYTESDBCOLUMNFLAGS_ISFIXEDLENGTH=truebinary
DBTYPE_BYTESDBCOLUMNFLAGS_ISFIXEDLENGTH=truevarbinary
DBTYPE_STRDBCOLUMNFLAGS_ISFIXEDLENGTH=truechar
DBTYPE_STRDBCOLUMNFLAGS_ISFIXEDLENGTH=truevarchar
DBTYPE_STRDBCOLUMNFLAGS_ISLONG=true 或最大长度大于 8000 个字符或未报告最大长度。text
DBTYPE_WSTRDBCOLUMNFLAGS_ISFIXEDLENGTH=truenchar
DBTYPE_WSTRDBCOLUMNFLAGS_ISFIXEDLENGTH=falsenvarchar
DBTYPE_WSTRDBCOLUMNFLAGS_ISLONG=true 或 最大长度大于 4000 个字符或未报告最大长度。ntext
DBTYPE_UDTError
DBTYPE_DATE*datetime
DBTYPE_DBDATEdatetime(必须显式转换)
DBTYPE_DBTIMEdatetime(必须显式转换)
DBTYPE_DBTIMESTAMP*datetime
DBTYPE_ARRAYError
DBTYPE_BYREFIgnored
DBTYPE_VECTORError
DBTYPE_RESERVEDError

* 表示如果SQL Server 中没有确切的等价数据类型,则转换为某种形式的SQL Server 类型。这种转换将导致精确度降低、上溢或下溢。如果SQL Server 的未来版本支持相应的数据类型,则默认的隐式映射可能会改变。

注意: numeric(p,s)

表示SQL Server的数据类型numeric精度为p,刻度为 s。对于DBTYPE_NUMERIC和DBTYPE_DECIMAL,允许使用的最大精度为38。创建访问器时,提供程序必须支持以DBTYPE_WSTR 绑定到DBTYPE_BSTR 列。DBTYPE_VARIANT列当作Unicode 字符串nvarchar使用。这需要提供程序支持从 DBTYPE_VARIANT 向 DBTYPE_WSTR 的转换。提供程序应按照 OLE DB 的定义实现该转换。

解释数据类型映射

>是否映射对SQL Server 类型由OLE DB数据类型和描述该列或数量值的DBCOLUMNFLAGS值共同确定。在使用COLUMNS架构行集时,由DATA_TYPE和COLUMN_FLAGS列来代表这些值。在使用IColumnsInfo::GetColumnInfo 接口时,由DBCOLUMNINFO结构的wType和 dwFlags 成员代表这些信息。

若要在包括特定的 DBTYPE 和 DBCOLUMNFLAG 值的给定列上用使用端映射,应在该表中寻找相应的SQL Server 类型。在表达式中远程表的列的类型规则可以通过如下的简单规则描述:

给定远程列的值在 Transact-SQL 表达式中是合法的条件为,它在上表中所映射的SQL Server 类型在相同的上下文中是合法的。

表和规则定义:

比较和表达式。通常,如果是可用于X数据类型和<远程列> 所映射数据类型上的有效运算符,则X <远程列> 就是一个有效表达式。 显式转换。允许 Convert (X, <远程列>) 的条件:<远程列> 的 DBTYPE 映射为本地数据类型 Y(如上表所示)而且允许从 Y 到 X 的显式转换。

如果用户要将远程数据转换为非默认本地数据类型,则必须使用显示转换。

若要在对远程表使用UPDATE 和 INSERT 语句时使用导出端映射,应使用同样的表将本地的SQL Server 数据类型映射为OLE DB数据类型。如果下述情况之一存在,则允许将SQL Server 类型 (S1) 映射为给定的OLE DB类型 (T):

相应的映射可以在映射表(表3)中直接找到。

允许S1隐式转换为另一种SQL Server类型S2,而S2对类型T的映射包含在映射表(表3)中。

大对象(LOB)的处理

如映射表(表3)中所述,如果DBTYPE_STR、DBTYPE_WSTR或DBTYPE_BSTR类型的列也报告DBCOLUMNFLAGS_ISLONG,或者它们的最大长度超过4,000个字符(或未报告最大长度),SQL Server 将相应把它们处理为 text或ntext列。类似地,对于DBTYPE_BYTES列,如果设置了DBCOLUMNFLAGS_ISLONG,或最大长度大于8,000个字节(或未报告最大长度),该列将被视为image列。Text、ntext和image列称为LOB列。

SQL Server不会在OLE DB提供程序的LOB上列出完整的文本或图像功能。在OLE DB提供程序的大对象上不支持TEXTPTRS 的;因此,也不支持相关的功能,例如,TEXTPTR 系统函数以及 READTEXT、WRITETEXT 和 UPDATETEXT 语句。支持检索整个 LOB 列的 SELECT 语句,也支持对远程表上整个大对象列的 UPDATE 和 INSERT 语句。

如果提供程序支持LOB列上的结构化存储接口,SQL Server 将使用它们。结构化存储接口如下所示(按优先权和功能的递增顺序排列):ISequentialStream、Istream 和 ILockBytes。如果提供程序支持这些接口中的一个或多个,当通过 IDBProperties 接口查询提供程序时,它必须将 DBPROPVAL_OO_BLOB 作为 DBPROP_OLEOBJECTS 属性的值返回。同样,提供程序应在 DBPROP_STRUCTUREDSTORAGE 属性中指出它所支持的接口。

如果提供程序不支持LOB列上的任何结构化存储接口,SQL Server 2000 将在自身实现该接口,同时仍将它们按text、ntext或image列列出。

访问 LOB 列

如果提供程序支持结构化存储接口之一,SQL Server在查询运行时按如下步骤检索LOB列:

在通过 IOpenRowset::OpenRowset打开行集合前,SQL Server 请求对大对象列上的一个或多个结构化存储接口(ISequentialStream、Istream 和 ILockBytes)的支持。提供程序支持的第一个接口是必需的;而其他接口则是可选的,可通过将 DBPROP 结构的 dwOptions 元素设置为 DBPROPOPTIONS_SETIFCHEAP 来请求它们。例如,如果提供程序同时支持 ISequentialStream 和 ILockBytes ,则 ISequentialStream 是必需的,而 ILockBytes 则是可选的。

打开行集后,SQL Server 使用 IRowsetInfo::GetProperties 来识别行集中可用的实际接口。提供程序返回的最后一个或最优先接口将被使用。当SQL Server 创建基于大对象列的访问器时,该列绑定为 DBTYPE_IUNKNOWN,绑定中 DBOBJECT 结构的 iid 元素设置为接口。

读取LOB列

使用被请求的结构化存储接口的接口指针(在 IRowset::GetData 生成的行缓冲区中返回)来读取大对象列。如果提供程序不支持同时打开多个 LOB(即不支持 DBPROP_MULTIPLE_STORAGEOBJECTS)并且该行有多个大对象列时,SQL Server 将把 LOB 复制到本地工作表中。

在LOB列上的UPDATE和INSERT 语句

SQL Server 通过向提供程序传递一个指向新的存储对象的指针来修改存储对象,而不使用提供程序所提供的接口。对于每个 LOB 列,存储对象上被更新或插入的值是使用选定的结构化存储接口创建的。根据操作是 UPDATE 还是 INSERT,指向存储对象的指针分别通过 IRowsetChange::SetData或IRowsetChange::InsertRow传递到提供程序。

错误处理

如果对OLE DB提供程序特定方法的调用返回错误代码,SQL Server将查找提供程序的扩展错误信息,然后将有关错误条件的信息返回给用户。

SQL Server使用由OLE DB指定的OLE DB错误对象。其中的高级步骤有:

如果方法调用返回来自提供程序的错误代码,SQL Server 将查找ISupportErrorInfo 接口。如果支持该接口,SQL Server 将调用 ISupportErrorInfo::InterfaceSupportsErrorInfo 来验证生成错误代码的接口是否支持该错误对象。

如果接口支持该错误对象,SQL Server将调用GetErrorInfo函数来获得一个指向当前错误对象的IErrorInfo接口指针。

SQL Server 使用IErrorInfo接口获得指向 IErrorRecords 接口的指针。

SQL Server 使用IErrorRecords来循环查找对象中的所有错误记录并获得对应于每个记录的错误信息文本。

安全性

当使用者连接到OLE DB提供程序时,通常情况下,除非使用者希望作为集成安全用户被验证,否则提供程序将需要用户 ID 和密码。在分布式查询中,SQL Server 将作为 OLE DB 提供程序的使用者(代表执行分布式查询的SQL Server 登录)。SQL Server 将当前的SQL Server登录映射为链接服务器上的用户ID和密码。

这些映射可以被用户指定用于给定的链接服务器,并可以通过系统存储过程sp_addlinkedsrvlogin和 sp_droplinkedsrvlogin来建立并管理。通过使用IDBProperties::SetProperties 来建立初始化组属性DBPROP_AUTH_USERID和DBPROP_AUTH_PASSWORD,由映射确定的用户ID和密码可在连接建立的过程中传递到提供程序。

当客户端通过Microsoft Windows NT的身份验证连接到SQL Server时,如果登录使用sp_addlinkedsrvlogin建立自身的映射,那么SQL Server 在连接建立的过程中将尝试模拟客户端的安全上下文并设置提供程序的DBPROP_AUTH_INTEGRATED 属性。此过程称为“委派”。只有 Windows 2000完全支持委派。在Windows NT 4.0或更早版本中,只有提供程序完全位于SQL Server 机器中并且没有通过网络连接到后端数据源时才支持委派。在这种情况下,Windows NT已验证的登录必须映射为特定的用户ID和密码才能访问链接服务器。

在确定了用于连接的安全上下文后,OLE DB提供程序将全面负责安全上下文的验证以及对数据源中数据对象的权限检查。

查询执行方案

执行分布式查询时,SQL Server与OLE DB提供程序进行交互有下述一个或多个方案:

远程查询

索引访问

单纯表扫描

UPDATE 和 DELETE 语句

INSERT 语句

传递查询

远程查询

SQL Server 生成一个SQL查询,它将计算出由提供程序完整执行的初始查询的一部分。该方案只能用于SQL 命令提供程序。SQL Server 通过生成SQL 查询将操作转给提供程序的程度取决于提供程序支持的SQL语法。提供程序应通过如下方式指出它的SQL 支持级别:

通过 DBPROP_SQLSUPPORT 属性指出SQL Minimum、ODBC Core 或SQL-92 Entry 级别。SQL Minimum语法级别是SQL Server 2000支持的新级别,它允许SQL Server向支持SQL简单子集的简单提供程序发送远程查询。该级别包含基本 SELECT语句,即不包括子查询、在 FROM 子句中使用多表(因此无联接)和GROUP BY的SELECT语句。有关SQL Server 用来为各语法级别的提供程序生成远程查询的SQL 语法的子集的详细信息。

通过支持各种SQL Server特有的属性来指出对个别SQL功能的支持,这些SQL功能没有包括在DBPROP_SQLSUPPORT报告的语法级别中。在本节后面描述了属性列表和SQL Server使用它们的方法。

SQL Server在Transact-SQL字符串中使用问号 (?) 作为参数标记的带参数查询命令。带参数查询命令可以用于SQL Server、Microsoft Jet 和 Oracle OLE DB 提供程序。对于其他提供程序,如果该提供程序支持Command对象的 ICommandWithParameters属性,并且至少满足如下条件之一,则也可以使用带参数查询命令:

提供程序通过DBPROP_SQLSUPPORT属性指出支持SQL Server的ODBC Core级别。

通过使用 IDBPProperties 支持SQL Server 特有的属性SQLPROP_DYNCMICSQL,提供程序指出对问号 (?) 参数标记的支持。。

系统管理员通过设置提供程序上的选项 Dynamic Parameters 来使SQL Server 生成带参数查询。

当SQL Server生成在远程执行的SQL文本时,表名和列名被提供程序的引用字符(IDBInfo 接口的 DBLITERAL_QUOTE 文字)引起来。如果不支持该文字,则表名和列名不会被引起来。

如果提供程序支持带参数查询执行,SQL Server将带参数查询执行策略视为执行一个远程表和本地表的联接。带参数查询根据由本地表中每一行生成的参数值重复执行。这种策略减少了从提供程序获取的行数,并且有利于行数较少的本地表联接到行数较多的远程表。远程联接策略可以使用 REMOTE 联接优化提示来强制执行。

下面是在远程查询方案中针对提供程序所进行的高级步骤:

SQL Server使用IDBCreateCommand::CreateCommand从Session对象创建Command对象。

如果将服务器配置选项Remote Query Timeout的值设置为大于零,SQL Server将使用 ICommandProperties::SetProperties把Command对象的DBPROP_COMMANDTIMEOUT设置为同样的值;必须调用ICommand::SetCommandText 来将命令文本设置为已生成的 Transact-SQL 字符串。

SQL Server 调用ICommandPrepare::Prepare 来准备命令。如果提供程序不支持该接口,SQL Server 将继续第 4 步。

如果生成的查询是带参数的,SQL Server 使用 ICommandWithParameters::SetParameterInfo 来描述这些参数并使用 IAccessor::CreateAccessor 创建使用这些参数的访问器。

SQL Server 调用 ICommand::Execute 来执行命令并创建行集。

SQL Server 使用 IRowset 接口浏览并使用表中的行。使用 IRowset::GetNextRows 获取行,使用 IRowset::RestartPosition 来重定位行集的起始点,使用 IRowset::ReleaseRows 释放行。

用于远程查询执行的提供程序属性

如果提供程序支持的SQL 功能没有包含在 DBPROP_SQLSUPPORT 报告的语法级别中,可以通过使用各种提供程序特有的属性来指出它们。

SQLPROP_GROUPBY。该属性对支持SQL-Minimum 级别的提供程序比较有意义。它指出提供程序在 SELECT 语句中支持 GROUP BY 和 HAVING 子句。另外,它还指出提供程序支持如下五种聚合函数:MIN、MAX、SUM、COUNT 和 AVG。提供程序可能不支持在这些合计函数参数中使用 DISTINCT。

SQLPROP_SUBQUERIES。该属性对支持SQL-Minimum 级别的提供程序比较有意义。它指出该提供程序支持SQL-92 entry 级别所规定的子查询。包括 SELECT 列表中的子查询,以及 WHERE 子句中的关系子查询,IN、EXISTS、ALL 和 ANY 运算符。

SQLPROP_DATELITERALS。该属性对任何提供程序(包括支持SQL-92 entry 级别的提供程序)都比较有意义。对日期时间文字的标准语法的支持不属于SQL-92 entry 级别。该SQL Server 特有的属性指出提供程序支持SQL-92 标准所规定的日期时间文字语法。

SQLPROP_ANSILIKE。该属性对支持SQL-Minimum 级别的提供程序比较有意义。它指出提供程序支持每个SQL-92 entry 级别所规定的 LIKE 运算符(使用 '%' 和 '_' 作为通配符)。由于SQL-Minimum 级别没有包括对 LIKE 的支持,所以它对支持SQL-Minimum 级别的提供程序非常有用。

SQLPROP_INNERJOIN。该属性对支持SQL-Minimum 级别的提供程序比较有意义。它指出支持在 FROM 子句中使用多个表。由于SQL-Minimum 级别不支持联接,所以它对只支持SQL-Minimum 级别的提供程序非常有用。但是,这并非指出了对显式 JOIN 关键字和 OUT 联接的支持。它只指出了支持在 FROM 子句使用多个表的隐含联接。

SQLPROP_DYNAMICSQL。该属性指出支持使用 '?' 作为参数标记。应支持参数标记在 WHERE 子句或 SELECT 列表中替代一个数量项目。对 '?' 运算符标记的支持允许SQL Server 向提供程序发送带参数查询。

SQLPROP_NESTEDQUERIES。该属性指出支持在 FROM 子句中嵌套 SELECT(例如,SELECT * FROM (SELECT * FROM T))。在多种情况下,SQL Server 在生成远程执行的查询字符串时,在查询的 FROM 子句中使用嵌套的 SELECT 语句。由于对嵌套 SELECT 的支持并不是SQL-92 entry 级别所必需的,除非提供程序也设置了本属性,否则SQL Server 不会向提供程序委派带有嵌套 SELECT 语句的查询。另外,系统管理员也可以设置提供程序的 Nested Queries 选项,以使SQL Server 生成用于提供程序上的嵌套查询。

提供程序能够通过使用名为SQLPROPSET_OPTHINTS 的SQL Server 特殊属性集来支持这些属性,并获得已定义的 PROPID 值。属性集SQLPROPSET_OPTHINTS 和这两个属性通过使用以下常数来定义:

extern const GUIDSQLPROPSET_OPTHINTS = { 0x2344480c, 0x33a7, 0x11d1,
{ 0x9b, 0x1a, 0x0, 0x60, 0x8, 0x26, 0x8b, 0x9e } };
enumSQLPROPERTIES {
SQLPROP_NESTEDQUERIES = 0x4,
    SQLPROP_DYNAMICSQL = 0x5,
    SQLPROP_GROUPBY = 0x6,
    SQLPROP_DATELITERALS = 0x7,
    SQLPROP_ANSILIKE = 0x8,
    SQLPROP_INNERJOIN = 0x9,
    SQLPROP_SUBQUERIES = 0x10
  };

隐含的字符集和排序顺序

SQL Server 2000支持在列级别上指定字符数据的排序。排序包括非 Unicode 字符数据(char 和 varchar 列)的字符集和排序顺序规范。对于Unicode数据(nchar 和 nvarchar 列),排序只指定了排序顺序。

只有在链接服务器使用的字符集(非 Unicode 数据)、排序顺序、字符串比较语法和本地服务器一致时,SQL Server 2000 才将字符串比较操作委派给提供程序。

在链接服务器是SQL Server时,SQL Server自动确定排序的兼容性。对于其他提供程序,系统管理员必须为SQL Server 指出给定的链接服务器上的字符数据的排序方式。在SQL Server 2000中,支持名为Collation Name的新的链接服务器选项。如果系统管理员确定链接服务器上采用的排序语法和SQL Server 标准语法一致,就能将Collation Name选项设置为排序名。Collation Name选项能够使用系统存储过程sp_serveroption 来设置。只有满足了如下两个条件时才应该设置该选项:

远程排序顺序和字符集与指定的SQL Server 排序一致。

OLE DB 提供程序使用的字符串比较的语法符合SQL-92 标准规范或等同于SQL Server 的比较语法。

为了向下兼容,仍支持SQL Server 7.0 中的 Collation Compatible 选项。将其设置为true 等于将 Collation Name 选项设置为SQL Server 主数据库的默认排序方式。新的应用程序应使用 Collation Name 选项,而不是 Collation Compatible 选项。

索引访问

SQL Server 使用提供程序列出的索引来执行分布式查询的某些谓词。该方案只能在用户设置提供程序选项Index as Access Path时才能用于索引提供程序。下面是在使用索引执行查询时SQL Server 在提供程序上运行的主要高级步骤:

通过使用完整的表名和索引名调用 IOpenRowset::OpenRowset 来打开索引行集。完整表名和索引名依据前面的远程查询方案中所述的方式生成。

通过使用完整表名调用 IOpenRowset::OpenRowset 来打开基本表行集。

通过调用 IRowsetIndex::SetRange 根据查询谓词设置索引行集的范围。

通过索引行集上的 IRowset 扫描索引行集的行。

使用检索到的索引行中的书签列来通过 IRowsetLocate::GetRowsByBookmark 从基本表行集中获取相应的行。

在基本表上打开行集时,行集属性 DBPROP_IRowsetLocate 和 DBPROP_BOOKMARKS 是必需的。

单纯表扫描

SQL Server 扫描提供程序的整个远程表并在本地运行所有的查询命令。通过调用IOpenRowset::OpenRowset 打开表中相应的行集。SQL Server使用目录、架构和对象名部分按以下方式来构造提供给 OPENROWSET 的表名:

每一个名称段都使用提供程序的引用字符 (DBLITERAL_QUOTE) 引用,然后使用 DBLITERAL_CATALOG_SEPARATOR 字符连接它们。

行集对象打开后,SQL Server 使用 IColumnsInfo 接口来验证该表运行时元数据是否和编译时的元数据一致。

SQL Server 使用 IRowset 接口浏览并使用表中的行。使用 IRowset::GetNextRows 获取行,使用 IRowset::RestartPosition 来重定位行集的起始点,使用 IRowset::ReleaseRows 释放行。

UPDATE和DELETE语句

要从SQL Server 分布式查询中对远程表进行更新和删除,必须满足如下条件:

提供程序必须支持在被更新或删除的表上使用 IOpenRowset 打开的行集的书签。

提供程序必须支持在被更新或删除的表上使用 IOpenRowset 打开的行集合上的 IRowsetLocate 和 IRowsetChange 接口。

IRowsetChange 接口必须支持更新 (SetData) 和删除 (DeleteRows) 方法。

如果提供程序不支持 ITransactionLocal,则仅在该提供程序设置了 Non-transacted 选项且语句不在用户事务中时,才允许使用 UPDATE/DELETE 语句。

如果提供程序不支持 ITransactionJoin,只有不在用户事务中时才允许 UPDATE/DELETE 语句。

下列行集属性是在被更新的表中打开的行集所必需的:DBPROP_IRowsetLocate、DBPROP_IRowsetChange 和 DBPROP_BOOKMARKS。将DBPROP_UPDATABILITY 行集属性设置为 DBPROPVAL_UP_CHANGE 还是 DBPROPVAL_UP_DELETE 取决于执行的操作是 UPDATE 还是 DELETE。

以下是在提供程序上运行 UPDATE 或 DELETE 操作的高级步骤:

SQL Server 通过 IOpenRowset 接口打开基本表行集。SQL Server 需要行集上的上述属性。

SQL Server 确定符合条件的将被更新或删除的行。

SQL Server 通过 IRowsetLocate 接口使用书签在符合条件的行中进行定位。

使用 IRowsetChange::SetData(用于 UPDATE 操作)或 IRowsetChange::DeleteRows(用于 DELETE 操作)在符合条件的行上作出所需的更改。

INSERT 语句

支持远程表上的 INSERT 语句的条件要比 UPDATE 和 DELETE 语句宽松:

提供程序必须支持在目的基本表中的行集上的 IRowsetChange::InsertRow 操作。

如果提供程序不支持 ITransactionLocal,则仅在链接服务器设置了 Non-transacted updates 选项且语句不在用户事务中时,才允许使用 INSERT 语句。

如果提供程序不支持 ITransactionJoin,只有不在用户事务中时才允许 INSERT 语句。

SQL Server 使用IOpenRowset::OpenRowset打开基本表的行集并调用IRowsetChange::InsertRow将新的行插入基本行集中。 传递查询

除了赋予ICommand的命令文本是用户提交的(不由SQL Server 解释)命令字符串外,本方案和“远程查询”方案类似。SQL Server 在调用ICommandText::SetCommandText 时使用DBGUID_DEFAULT作为文字标识符。DBGUID_DEFAULT 指出提供程序应使用它的默认语法。如果该命令文本返回多个结果集(例如,如果该命令调用一个返回多个结果集的存储过程),SQL Server 将只使用命令返回的第一个结果集。

总结

MicrosoftSQL Server 2000 为访问异类数据源中的数据提供了最可靠的一套工具。通过了解SQL Server 提供的 OLE-DB 接口,开发人员能够更好地控制和完善分布式查询。

附录 A:SQL Server 采用的 OLE DB 接口

下表(表4)列出了SQL Server 使用的全部OLE DB 接口。“必要”列说明该接口是SQL Server所需的OLE DB功能中最基本的部分,还是可选的。如果一个给定的接口未标记为必要,SQL Server 仍然能够访问提供程序,但是某些特殊的SQL Server 功能或优化功能不能用于该提供程序。

对于可选接口,“方案”列指定了使用该接口的方案(是六个方案中的一个或多个)。例如,基本表行集上的 IRowsetChange 接口是可选接口;该接口用于 UPDATE 和 DELETE 语句方案以及 INSERT 语句方案中。如果该接口不被支持,则对提供程序的 UPDATE、DELETE 和 INSERT 语句也不能被支持。其他一些可选接口的“方案”列中标记为“性能”,表示该接口能够提高性能。例如,如果不支持 IDBSchemaRowset 接口,SQL Server 必须打开行集两次:一次获得元数据,另一次执行查询。通过支持IDBSchemaRowset,将提高SQL Server 的性能。

表 4:SQL Server 采用的接口

对象接口必要注释方案
Data Source 对象IDBInitialize初始化并设置数据和安全上下文。
IDBCreateSession创建 DB 会话对象。
IDBProperties获得有关提供程序功能的信息,设置初始化属性,必要属性:DBPROP_INIT_TIMEOUT。
IDBInfo获得引用文字、目录、名称、部分、分隔符、字符等等。远程查询。
DB Session 对象IDBSchemaRowset获得表/列的元数据。

需要的行集:

TABLES、COLUMNS、PROVIDER_TYPES;

其他可能用到的行集:INDEXES、TABLE_STATISTICS。

性能,索引访问。
IOpenRowset打开表、索引和柱状图上的行集。
IGetDataSource用于从 DB 会话对象返回到 DSO。
IDBCreateCommand用于为支持查询的提供程序创建命令对象(查询)。远程查询,传递查询。
ITransactionLocal用于事务方式的更新。UPDATE、DELETE 和 INSERT 语句。
ITransactionJoin用于分布式事务支持。如果在用户事务中,则必需有 UPDATE、DELETE 和 INSERT 语句。
Rowset 对象IRowset扫描行。
IAccessor绑定到行集中的列。
IColumnsInfo获得行集中的列信息。
IRowsetInfo获得行集属性的信息。
IRowsetLocateUPDATE/DELETE 操作和基于索引的查找所需;用于使用书签来查找行。索引访问,UPDATE 和 DELETE 语句。
IRowsetChange对行集进行 INSERTS/UPDATES/

DELETES 操作所需的。基于基本表的行集应支持该接口的 INSERT、UPDATE 和

DELETE 语句。

UPDATE、DELETE 和 INSERT 语句。
IConvertType用于验证该行集是否支持它的列上的数据类型转换。
IndexIRowset扫描行。索引访问,性能。
IAccessor绑定到行集中的列。索引访问,性能。
IColumnsInfo获得行集中的列信息。索引访问,性能。
IRowsetInfo获得行集属性的信息。索引访问,性能。
IRowsetIndex只用于索引上的行集合;用于索引功能(设置范围、搜索)。索引访问,性能。
CommandICommand远程查询,传递查询。
ICommandText用于定义查询文本。远程查询,传递查询。
IColumnsInfo用于获得查询结果需要的列元数据。远程查询,传递查询。
ICommandProperties用于指定根据命令返回的行集合上所需的属性。远程查询,传递查询。
ICommandWithParameters用于带参数查询命令。远程查询,性能。
ICommandPrepare用于准备获取元数据的命令(如果可用,用于传递查询中)。远程查询,性能。
Error 对象IErrorRecords用于获得指向 IErrorInfo 接口的对应于个别错误记录的指针。
IErrorInfo用于获得指向 IErrorInfo 接口的对应于个别错误记录的指针。
任意对象ISupportErrorInfo用于验证给定的接口是否支持错误对象。

注意:Index对象、Command 对象和Error对象不是强制的。如果它们被支持,则在“必要”列中指定的接口是强制的。

附录B: 用于生成远程查询的SQL子集

SQL Server 查询处理器根据SQL 命令提供程序生成的SQL 子集取决于提供程序依据 DBPROP_SQLSUPPORT 属性所支持的语法级别。

支持SQL Entry级别和ODBC Core的SQL命令提供程序

SQL Server将下面的SQL语言的子集用于由SQL 命令提供程序执行的查询,这些SQL 命令提供程序必须支持SQL-92 Entry 级别或 ODBC Core :

包含SELECT、FROM、WHERE、GROUP BY、UNION、UNION ALL、ORDER BY DESC、ASC 和 HAVING 子句的 SELECT 语句。

UNION 和 UNION ALL 只能在支持SQL-92 Entry 级别的提供程序上生成,不能在支持 ODBC Core 的提供程序上生成。

SELECT 子句: 在 SELECT 列表中的分级子查询。

不带 AS 关键字的列别名。 FROM 子句: 没有使用显式 JOIN 关键字;使用逗号分隔的表名指定内部联接,在远程查询中没有指定外部联接。

嵌套查询的格式:FROM ( <嵌套查询> ) <别名>。

不带 AS 关键字的表别名。 WHERE 子句使用带有 [NOT] EXISTS、ANY 和 ALL 的子查询。

表达式: 聚合函数:MIN([DISTINCT])、MAX([DISTINCT])、COUNT([DISTINCT])、SUM([DISTINCT])、AVG([DISTINCT]) 和 COUNT(*)。

比较运算符:<、=、<=、>、<>、>=、IS NULL 和 IS NOT NULL。

布尔运算符:AND、OR 和 NOT。

数学运算符:+、-、* 和 /。 常数: 数字和货币常数总是由 () 括住。

字符常数使用 '' 引住。

支持SQL Minimum 级别的SQL命令提供程序

对于支持SQL Minimum级别的SQL命令提供程序,SQL Server生成如下语法的SQL。

此处的语法来自ODBC 3.0中描述的SQL Minimum 语法。所有与该语法的不同之处都被突出显示。以粗斜体显示的项目就是添加到ODBC 3.0 所述的SQL Minimum 语法中的项目。以绿色删去的项目是从该语法中删除的项目。

select-statement ::=
SELECT [ALL | DISTINCT] select-list
FROM table-reference-list
[WHERE search-condition]
[order-by-clause]
SELECT clause
select-list ::=   * | select-sublist [, select-sublist]... 
select-sublist ::=    expression [alias]
alias ::=     user-defined-name
FROM clause
table-reference-list ::=   table-reference
table-identifier ::=   user-defined-name
table-name ::=    table-identifier
table-reference ::=  table-name
WHERE clause
search-condition ::=  boolean-term [OR search-condition]
boolean-term ::=    boolean-factor [AND boolean-term]
boolean-factor ::=  [NOT] boolean-primary
boolean-primary ::=  comparison-predicate | ( search-condition )
comparison-predicate ::=  expression  comparison-operator  expression
   | expression IS [NOT] NULL
comparison-operator ::=  < | > | <= | >= | = | <>
ORDER BY clause
order-by-clause ::=   ORDER BY sort-specification [, sort-specification]...
sort-specification ::=  { | column-name } [ASC | DESC]
Common syntactic elements
expression ::=    term | expression {+|–} term
term ::=     factor | term {*|/} factor
factor ::=    [+|–] primary
primary ::=    column-name
| literal
| ( expression )
column-name ::=    [table-name.]column-identifier
literal ::=    character-string-literal
   | integer-literal
     | exact-numeric-literal
character-string-literal ::=  '{character}?
(字符指驱动程序或数据源的字符集中的任意字符。
要在字符串中包括引号字符 ('),请使用两个引号字符 ('')。)
integer-literal ::=   [+ | -] unsigned-integer
exact-numeric-literal::=  [+ | -] unsigned-integer [period unsigned-integer]
   | period unsigned-integer
base-table-name ::=  base-table-identifier
base-table-identifier ::=  user-defined-name
column-identifier ::=  user-defined-name
user-defined-name ::=  letter[digit | letter | _]...
unsigned-integer ::=  {digit}?digit ::=     0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 
period ::=   .

Tags:SQL Server 分布式

编辑录入:爽爽 [复制链接] [打 印]
赞助商链接