本文描述 Microsoft SQL Server 查詢處理器如何與 OLE DB 提供者互動,以啟用分散式查詢和異質性查詢。 它主要供 OLE DB 提供者開發人員使用,並假設對 OLE DB 規格有深入的瞭解。 重點在於 SQL Server 查詢處理器與 OLE DB 提供者之間的 OLE DB 介面,而不是在分散式查詢功能本身。 如需分散式查詢功能的完整描述,請參閱連結伺服器 (資料庫引擎)。
概觀和術語
在 Microsoft SQL Server 中,分散式查詢可讓 SQL Server 使用者存取 SQL Server 伺服器以外的資料,可能是在執行 SQL Server 的其他伺服器中,或是在公開 OLE DB 介面的其他資料來源中。 OLE DB 可讓您以一致的方式從異質資料來源存取表格式資料。
針對本文的目的,分散式查詢是參考一或多個外部 OLE DB 資料來源中資料表和資料列集的任何 SELECT、INSERT、UPDATE 或 DELETE 陳述式。
遠端資料表是儲存在 OLE DB 資料來源中的資料表,並來自執行 SQL Server 的伺服器 (執行查詢的伺服器) 外部。 分散式查詢會存取一或多個遠端資料表。
OLE DB 提供者類別
下列清單是根據 SQL Server 分散式查詢觀點的 OLE DB 提供者功能進行分類。 根據定義,這些並不相互排斥;指定的提供者可能屬於下列多個類別:
SQL 命令提供者
支援 Command SQL Server 辨識之 SQL 標準方言的物件提供者屬於此類別。 任何一個 OLE DB 提供者必須符合下列特定需求,SQL Server 才會將它視為 SQL 命令提供者:
提供者必須支援
Command物件及其所有的必要 OLE DB 介面:ICommand、ICommandText、IColumnsInfo、ICommandProperties和IAccessor。提供者支援的 SQL 方言必須至少為 SQL Subminimum。 提供者必須透過
DBPROP_SQLSUPPORT屬性來報告方言。
SQL 命令提供者的範例為 Microsoft OLE DB Provider for SQL Server 和 Microsoft OLE DB Provider for ODBC。
索引提供者
索引提供者是指根據 OLE DB 支援和公開索引,並允許以索引方式查閱基底資料表的提供者。 任何一個 OLE DB 提供者必須符合下列特定需求,SQL Server 才會將它視為索引提供者:
提供者必須支援
IDBSchemaRowset具有 和COLUMNSINDEXES結構描述資料列集的TABLES介面。提供者必須支援透過
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 Enterprise Manager 中的 [Linked Server Properties] 對話方塊可用來設定這些選項。
簡單資料表提供者
這些是指公開針對基底資料表透過 IOpenRowset 介面開啟資料列集方式的提供者。 這類提供者既不是 SQL 命令提供者,也不是索引提供者;相反地,它們是 SQL Server 分散式查詢可以使用的最簡單的提供者類別。
針對這類提供者,SQL Server 只能在分散式查詢評估期間執行資料表掃描。
非 SQL 命令提供者
支援 Command 物件及其必要介面,但不支援 SQL Server 所辨識的 SQL 標準方言的提供者,屬於此類別。
非 SQL 命令提供者的兩個範例為 Microsoft OLE DB Provider for Indexing Service 和 Microsoft OLE DB Provider for Microsoft Active Directory Service。
Transact-SQL 子集
如果提供者支援所需的 OLE DB 介面,則分散式查詢支援下列每個 Transact-SQL 陳述式類別。
容許所有
SELECT陳述式,但以遠端表格作為目的地表格的陳述式除外SELECT INTO。如果提供者支援 INSERT 的必要介面,即可在遠端資料表上使用
INSERT陳述式。 如需 的 OLE DB 需求的INSERT詳細資訊,請參閱本文稍後的 INSERT 陳述式 。UPDATE如果DELETE提供者符合指定資料表上的 OLE DB 介面需求,則允許針對遠端資料表使用陳述式。 如需可以更新或刪除遠端資料表的 OLE DB 介面需求和條件,請參閱本文稍後的 UPDATE 和 DELETE 陳述式 。
游標支援
如果提供者支援必要的 OLE DB 功能,則快照游標和鍵集合游標皆可用於分散式查詢。 分散式查詢不支援動態資料指標。 使用者對分散式查詢提出的動態游標要求會被降級為鍵集游標。
快照游標會在游標開啟時移入,且結果集保持不變;基礎資料表的更新、插入和刪除不會反映在游標中。
索引鍵集游標會在游標開啟時填入,且結果集會在整個游標存續期間保持不變。 不過,在瀏覽資料列之後,即會在資料指標中看見對基礎資料表所做的更新和刪除。 不顯示可能影響游標成員資格的基礎資料表的插入。
如果提供者符合遠端表格 (例如, table UPDATE 或 DELETE <remote-table> WHERE CURRENT OF <cursor-name>) 上的更新及刪除條件,則可以透過在分散式查詢上定義並參照遠端表格的游標來更新或刪除遠端表格,以更新或刪除遠端表格。 如需詳細資訊,請參閱本文稍後的 UPDATE 和 DELETE 陳述式 。
索引鍵集游標支援需求
如果符合所有 Transact-SQL 語法需求,且下列任一項存在,則分散式查詢支援鍵集游標:
OLE DB 提供者可支援在查詢中的所有遠端資料表上重複使用書籤。 可重複使用書籤可從指定資料表的資料列集使用,並用於相同資料表的不同資料列集。 可重複使用書籤的支援會透過
TABLES_INFO將IDBSchemaRowset資料行設定為BOOKMARK_DURABILITYBMK_DURABILITY_INTRANSACTION或更高的持久性來指出的結構描述資料列集。所有遠端資料表都會透過介面的資料
IDBSchemaRowset列集公開INDEXES唯一的索引鍵。 應該有一個索引項目,直欄設定UNIQUE為VARIANT_TRUE。
不支援涉及 OpenQuery 函式的分散式查詢使用金鑰集游標。
可更新的索引鍵集游標需求
可以透過分散式查詢上定義的索引鍵集游標來更新或刪除遠端表格,例如 UPDATEDELETE <remote-table> WHERE CURRENT OF <cursor-name>或 。 必須符合下列條件,可更新的資料指標才允許用於分散式查詢:
若提供者符合在遠端資料表上進行更新及刪除的條件,則允許使用可更新的資料指標。 如需詳細資訊,請參閱本文稍後的 UPDATE 和 DELETE 陳述式 。
所有可更新鍵集游標的操作都必須在使用者定義的交易中,並需具備可重複讀取隔離等級或更高的隔離等級。 此外,提供者必須使用
ITransactionJoin介面來支援分散式交易。
OLE DB 提供者互動階段
所有分散式查詢執行案例有共通的六項作業:
連接建立和屬性擷取作業指出 SQL Server 如何連接到 OLE DB 提供者,以及使用了哪些提供者屬性。
資料表名稱解析和中繼資料擷取作業指出 SQL Server 如何將遠端資料表名稱 (以兩種方式之一指定:連結伺服器型名稱或臨機操作名稱) 解析為提供者中的適當資料物件。 這也包括 SQL Server 從提供者擷取的資料表中繼資料,以編譯和優化分散式查詢。
交易管理操作指定所有與 OLE DB 提供者的交易相關互動。
資料類型處理作業指出 SQL Server 在處理分散式查詢期間從 OLE DB 提供者使用資料或將資料匯出到其中時,如何處理 OLE DB 資料類型。
錯誤處理作業指出 SQL Server 如何使用來自提供者的延伸錯誤資訊。
安全性作業指定 SQL Server 安全性如何與提供者的安全性互動。
連接建立和財產檢索
SQL Server 支援兩種遠端資料物件命名慣例:以連結伺服器為基礎的四部分名稱,以及使用 OPENROWSET 函式的特定名稱。
以連結伺服器為基礎的名稱
連結的伺服器可作為 OLE DB 資料來源抽象層。 以連結伺服器為基礎的名稱是四部分名稱的形式 <linked-server>.<catalog>。
<schema>.<object>,其中 <linked-server> 是連結的伺服器名稱。 SQL Server 會解譯 <linked-server> 來衍生 OLE DB 提供者,以及識別提供者資料來源的連接屬性。 其他三個名稱部分則是由 OLE DB 資料來源解譯,以識別特定的遠端資料表。 :::
臨時名稱
特定名稱是以 OPENROWSET 或 OPENDATASOURCE 函式為基礎的名稱。 其中包含每次在分散式查詢中參考遠端資料表時的所有連接資訊 (也就是所要使用的 OLE DB 提供者、識別資料來源所需的屬性、使用者識別碼和密碼)。
預設不允許使用臨機操作名稱,但系統管理員角色的成員除外。 若要對 OLE DB 提供者使用特定名稱,則應將提供者選項 DisallowAdhocAccess 設定為 0。
如果使用連結的伺服器名稱,SQL Server 會從連結的伺服器定義擷取 OLE DB 提供者名稱和提供者的初始化屬性。 如果使用特定名稱,SQL Server 會從 OPENROWSET 函式的引數擷取相同資訊。
如需使用四部分名稱和臨機操作名稱型語法設定連結伺服器的詳細指示,請參閱建立連結伺服器 (SQL Server 資料庫引擎)。
連線到 OLE 資料庫提供者
以下是當 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提供者選項,將提供者設定為「進程內」或「進程外」的具現化方式。 如需詳細資訊,請參閱設定提供者選項。若要深入了解 OLE DB 服務元件和工作階段共用,請參閱提供者需求的相關 OLE DB 文件。
資料來源經過初始化。
建立 DSO 之後,如果伺服器組態選項
remote login timeout大於 0,介面會IDBProperties設定DBPROP_INIT_TIMEOUT初始化屬性;這是必要的屬性。如果這些屬性是在連結伺服器定義或函式的
OPENROWSET第二個引數中指定或隱含,則會設定這些屬性:DBPROP_INIT_PROVIDERSTRINGDBPROP_INIT_DATASOURCEDBPROP_INIT_LOCATIONDBPROP_INIT_CATALOGDBPROP_AUTH_USERIDDBPROP_AUTH_PASSWORD
設定這些屬性之後,系統會呼叫
IDBInitialize::Initialize以使用指定的屬性將 DSO 初始化。SQL Server 收集提供者特定的資訊。
SQL Server 會收集要用於分散式查詢評估的數個提供者屬性;這些屬性是透過呼叫
IDBProperties::GetProperties來擷取。 所有這些屬性都是選擇性的;不過,支援所有相關屬性可讓 SQL Server 充分利用提供者的功能。 例如,若要判斷 SQL Server 是否可以傳送查詢給提供者,則需要DBPROP_SQLSUPPORT。 如果不支援此屬性,SQL Server 不會使用遠端提供者作為 SQL 命令提供者,即使它是 SQL 命令提供者也一樣。 在下表中,[預設值] 資料行指出 SQL Server 在提供者不支援屬性時所採用的值。屬性 預設值 使用 DBPROP_DBMSNAME無 用於錯誤訊息。 DBPROP_DBMSVER無 用於錯誤訊息。 DBPROP_PROVIDERNAME無 用於錯誤訊息。 DBPROP_PROVIDEROLEDBVER11.5 用於判斷 2.0 功能的可用性。 DBPROP_CONCATNULLBEHAVIOR無 用於判斷提供者的 NULL串連行為是否與 SQL Server 相同。DBPROP_NULLCOLLATION無 只有在 NULLCOLLATION符合 SQL Server 執行個體的 Null 定序行為時,才允許用於排序/索引。DBPROP_OLEOBJECTS無 判斷提供者是否支援大型資料物件資料行的結構化儲存介面。 DBPROP_STRUCTUREDSTORAGE無 判斷大型物件類型支援哪些結構化儲存介面 ( ILockBytes、Istream和ISequentialStream)。DBPROP_MULTIPLESTORAGEOBJECTS否 判斷是否允許同時開啟多個大型物件欄位。 DBPROP_SQLSUPPORT無 判斷是否可以將 SQL 查詢傳送給提供者。 DBPROP_CATALOGLOCATIONDBPROPVAL_CL_START用於建構多部分資料表名稱。 SQLPROP_DYNAMICSQL否 SQL Server 特定屬性:如果它傳回 VARIANT_TRUE,則指出支援將?參數標記用於參數化查詢執行。SQLPROP_NESTEDQUERIES否 SQL Server 特定屬性:如果它傳回 VARIANT_TRUE,則指出提供者支援SELECT子句中的巢狀FROM陳述式。SQLPROP_GROUPBY否 SQL Server 特定屬性:如果傳回 VARIANT_TRUE,則表示提供者GROUP BY支援陳述式中的SELECT子句,如 SQL-92 標準所指定。SQLPROP_DATELITERALS否 SQL Server 特定屬性:如果返回 VARIANT_TRUE,表示提供者根據 SQL Server Transact-SQL 語法支援日期時間文字常量。SQLPROP_ANSILIKE否 SQL Server 特定屬性:此屬性對於支援 SQL 最低層級的提供者很重要,且根據 SQL-92 入門層級支援 LIKE運算子 (以 '%' 和 '_' 作為萬用字元)。SQLPROP_SUBQUERIES否 SQL Server 屬性:此屬性對於支援 SQL 最低層級的提供者很重要。 此屬性表明提供者支援 SQL-92 基礎層級所指定的子查詢。 這包括 SELECT清單和WHERE子句中的子查詢,並支援相互關聯子查詢的IN、EXISTS、ALL和ANY運算子。SQLPROP_INNERJOIN否 SQL Server 特定屬性:此屬性對於支援 SQL 最低層級的提供者很重要。 此屬性指出支援在 FROM子句中使用多個資料表進行聯結。從
IDBInfo::GetLiteralInfo擷取以下三個常值:DBLITERAL_CATALOG_SEPARATOR、DBLITERAL_SCHEMA_SEPARATOR(用於建構完整的物件名稱,包括目錄、結構和物件名稱部分),以及DBLITERAL_QUOTE(用於在傳送給提供者的 SQL 查詢中為識別符名稱加上引號)。如果提供者不支援分隔字元常值,SQL Server 會使用句點 (.) 作為預設分隔字元。 如果提供者只支援目錄分隔符號字元,但不支援結構描述分隔符號字元,SQL Server 也會使用目錄分隔符號字元作為結構描述分隔符號字元。 如果提供者不支援
DBLITERAL_QUOTE,SQL Server 會使用單引號 (') 作為引號字元。注意
如果提供者的名稱分隔符號常值不符合這些預設值,提供者必須公開
IDBInfo它們,讓 SQL Server 透過四個部分的名稱存取其資料表。 如果未公開這些常值,則只能針對這類提供者使用傳遞查詢。
如需公開 SQLPROP_DYNAMICSQL 和 SQLPROP_NESTEDQUERIES 屬性的資訊,請參閱 SQL Server 特定屬性。
資料表名稱解析和中繼資料擷取
SQL Server 會將分散式查詢中的指定遠端資料表名稱,解析為 OLE DB 資料來源中的特定資料表或檢視表。 以連結伺服器為基礎的命名配置和特定命名配置都會產生三部分名稱供提供者解譯。 在以連結伺服器為基礎的名稱案例中,四部分名稱的最後三個部分是由目錄、結構描述和物件名稱組成。 在特定名稱案例中,OPENROWSET 函式第三個引數會指定描述目錄、結構描述和物件名稱的三部分名稱。 目錄名稱和結構描述名稱之一或兩者可為空白 (具有空白目錄名稱和結構描述名稱的四部分名稱看起來像是 <server-name>...<object-name>)。在此情況下,SQL Server 會使用 NULL 作為要在結構描述資料列集資料表中尋找的對應值。
SQL Server 所採用的名稱解析規則和中繼資料擷取步驟取決於提供者是否支援 IDBSchemaRowset 物件上的 Session 介面。
如果支援 IDBSchemaRowset,則會從 TABLES 介面使用 COLUMNS、INDEXES、TABLES_INFO 和 IDBSchemaRowset 結構描述資料列集 (TABLES_INFO 結構描述資料列集是在 OLE DB 2.0 中定義)。SQL Server 會限制 IDBSchemaRowset 介面所傳回的結構描述資料列集,以尋找符合指定遠端資料表名稱部分的結構描述資料列。 以下是與提供者對結構描述資料列集所支援的限制相關的規則,以及 SQL Server 如何使用這些限制來擷取遠端資料表的中繼資料:
對
TABLE_NAME和COLUMN_NAME欄的限制為一律必要。如果提供者支援
TABLE_CATALOG(或TABLE_SCHEMA) 上的限制,SQL Server 會在TABLE_CATALOG(或TABLE_SCHEMA) 上使用該限制。 如果未在遠端資料表名稱中指定目錄 (或結構描述) 名稱,則會使用值NULL作為對應的限制值。 如果指定了目錄 (或結構描述) 名稱,提供者必須支援TABLE_CATALOG(或TABLE_SCHEMA) 上的對應限制。提供者必須同時支援
TABLE_SCHEMA和TABLES中COLUMNS資料行上的限制,或兩者都不支援。 提供者必須同時支援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 必須是有效的非 Null 值。
從選擇性 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 會尋找指定遠端資料表的其他資訊,例如書籤支援、類型和書籤長度。 這會使用 DESCRIPTION 資料列集的 TABLES_INFO 資料行以外所有資料行。
TABLES_INFO 資料列集中的資訊使用方式如下:
BOOKMARK_DURABILITY欄可用於實作更有效率的索引鍵集游標。 如果此資料行具有BMK_DURABILITY_INTRANSACTION的值或更高可靠性值,SQL Server 會利用書籤來擷取並更新遠端資料表資料列,以實現索引鍵集資料指標。BOOKMARK_TYPE、 和BOOKMARK_DATA_TYPEBOOKMARK_MAXIMUM_LENGTH直欄可用來在查詢編譯時判斷書籤中繼資料。 如果不支援這些資料行,SQL Server 會在編譯期間開啟基底資料表資料列集IOpenRowset,以取得書籤資訊。
如果不支援,且遠端資料表名稱包含目錄或結構描述名稱,則 IDBSchemaRowset SQL Server 需要 IDBSchemaRowset 並傳回錯誤。 不過,如果未提供目錄或結構描述名稱,SQL Server 會開啟對應至遠端資料表的資料列集,並從資料列集物件的必要 IColumnsInfo 介面擷取資料行中繼資料。
SQL Server 會透過呼叫 IOpenRowset::OpenRowset 來開啟對應到資料表的資料列集。 提供給 OPENROWSET 的資料表名稱是從目錄、結構描述和物件名稱部分建構而來。
每個名稱部分 (
catalog、schema、object name) 都會以提供者的引號字元 (DBLITERAL_QUOTE) 括住,然後在其間內嵌DBLITERAL_CATALOG_SEPARATOR字元和DBLITERAL_SCHEMA_SEPARATOR字元來串連。 名稱建構會遵循IOpenRowset中的 OLE DB 規則。資料表
IColumnsInfo::GetColumnInfo的資料行中繼資料會在開啟資料列集物件之後擷取。
如果不支援 TABLES、 COLUMNS和TABLES_INFO資料列集,SQL IDBSchemaRowset Server 會針對基底資料表開啟資料列集兩次:一次是在查詢編譯期間以擷取中繼資料,另一次是在查詢執行期間。 如果提供者在開啟資料列集時會產生副作用 (例如執行改變即時裝置狀態的程式碼、傳送電子郵件、執行使用者提供的任意程式碼),則必須注意此行為。
統計資料擷取
如果提供者支援基底資料表的散發統計資料,則 SQL Server 會使用這些統計資料。 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 2.6 規格。
條件約束
如果 OLE DB 提供者支援 OLE DB 2.6 結構描述資料列集 CHECK,SQL Server 查詢最佳化工具也會使用定義於遠端資料來源中基底資料表的 CHECK_CONSTRAINTS_BY_TABLE 條件約束。 結構描述資料列集 CHECK_CLAUSE 資料行應該以符合 SQL-92 規範的語法傳回 CHECK 子句述詞。 查詢最佳化工具使用條件約束資訊以消除或簡化已知一律為 false 或一律為 true 的述詞,因為資料表上存在 check 條件約束。
交易管理
SQL Server 支援使用提供者的 ITransactionLocal (適用於本機交易) 與 ITransactionJoin (適用於分散式交易) OLE DB 介面,以交易方式存取分散式資料。 藉由對提供者啟動本機交易,SQL Server 保證寫入作業的原子性。 藉由使用分散式交易,SQL Server 可確保涉及到多個節點的交易在所有節點中都有相同結果 (認可或中止)。 如果提供者不支援必要的 OLE DB 交易相關介面,則不允許針對該提供者進行更新作業,視本機交易內容而定。
下表描述當使用者根據提供者的功能和本機交易內容執行分散式查詢時所發生狀況。 對提供者的讀取作業是指執行SELECT陳述式,或是在SELECT INTO、INSERT、UPDATE或DELETE陳述式中將遠端資料表讀入其輸入端。 針對提供者的寫入作業指的是 INSERT、UPDATE 或 DELETE 陳述式,並以遠端資料表作為目標資料表。
根據提供者功能和交易內容,分散式查詢的結果如下:
| 發生分散式查詢 | 提供者不支援 ITransactionLocal |
提供者支援 ITransactionLocal 但不支援 ITransactionJoin |
提供者同時支援 ITransactionLocal 和 ITransactionJoin |
|---|---|---|---|
| 在單一交易中 (並非使用者發起的交易)。 | 根據預設,只允許讀取作業。 啟用提供者層級選項 Nontransacted Updates 時,允許寫入作業。 (啟用此選項時,SQL Server 無法保證提供者資料的不可部分完成性和一致性。這可能會導致寫入作業的部分影響反映在遠端資料來源中,而無法復原它們。 |
允許對遠端資料執行所有陳述式。 索引鍵集資料指標是唯讀的。 本機交易會在提供者上使用目前 SQL Server 工作階段的隔離等級開始,並在指令執行成功後提交。 (SQL Server 會話的預設隔離層級是 READ COMMITTED ,除非使用陳述式進行 SET TRANSACTION ISOLATION LEVEL 修改。提供者必須支援要求的隔離層級。 |
允許所有說法。 索引鍵集資料指標是唯讀的。 本地交易以目前 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 使用資料時,將 OLE DB 資料類型對應到 SQL Server 原生類型,並在 SQL Server 匯出資料時,將 SQL Server 原生類型對應到 OLE DB 資料類型。 除非另外註明,否則會以隱含方式進行此對應。
您可以使用下列兩種對應方法之一來處理分散式查詢中的資料類型:
取用端對應會將類型從 OLE DB 資料類型對應至取用端的 SQL Server 原生資料類型,當遠端資料表出現在陳述式中
SELECT,以及 、UPDATE和DELETE陳述式的INSERT輸入端時。當遠端資料表是
INSERT或UPDATE陳述式的目的地資料表時,匯出端對應會將 SQL Server 資料類型對應到 OLE DB 資料類型。
SQL Server 和 OLE DB 資料類型對應表。
| OLE DB 類型 | DBCOLUMNFLAG |
SQL Server 資料類型 |
|---|---|---|
DBTYPE_I1
1 |
數值(3, 0) | |
DBTYPE_I2 |
smallint | |
DBTYPE_I4 |
int | |
DBTYPE_I8 |
數字(19,0) | |
DBTYPE_UI1 |
tinyint | |
DBTYPE_UI2
1 |
數字(5,0) | |
DBTYPE_UI4
1 |
數字(10,0) | |
DBTYPE_UI8
1 |
數字(20,0) | |
DBTYPE_R4 |
float | |
DBTYPE_R8 |
real | |
DBTYPE_NUMERIC |
numeric | |
DBTYPE_DECIMAL |
decimal | |
DBTYPE_CY |
money | |
DBTYPE_BSTR |
DBCOLUMNFLAGS_ISFIXEDLENGTH=true或 長度上限 > 4,000 個字元 |
ntext |
DBTYPE_BSTR |
DBCOLUMNFLAGS_ISFIXEDLENGTH=true |
nchar |
DBTYPE_BSTR |
DBCOLUMNFLAGS_ISFIXEDLENGTH=false |
nvarchar |
DBTYPE_IDISPATCH |
錯誤 | |
DBTYPE_ERROR |
錯誤 | |
DBTYPE_BOOL |
bit | |
DBTYPE_VARIANT
1 |
nvarchar | |
DBTYPE_IUNKNOWN |
錯誤 | |
DBTYPE_GUID |
uniqueidentifier | |
DBTYPE_BYTES |
DBCOLUMNFLAGS_ISLONG=true或 最大長度 > 8,000 |
圖像 |
DBTYPE_BYTES |
DBCOLUMNFLAGS_ISROWVER=true, DBCOLUMNFLAGS_ISFIXEDLENGTH=true, 資料行大小 = 8或 未回報最大長度。 |
時間戳記 |
DBTYPE_BYTES |
DBCOLUMNFLAGS_ISFIXEDLENGTH=true |
binary |
DBTYPE_BYTES |
DBCOLUMNFLAGS_ISFIXEDLENGTH=true |
varbinary |
DBTYPE_STR |
DBCOLUMNFLAGS_ISFIXEDLENGTH=true |
煳 |
DBTYPE_STR |
DBCOLUMNFLAGS_ISFIXEDLENGTH=true |
瓦查爾 |
DBTYPE_STR |
DBCOLUMNFLAGS_ISLONG=true或 長度上限 > 8,000 個字元 或 未回報最大長度。 |
簡訊 |
DBTYPE_WSTR |
DBCOLUMNFLAGS_ISFIXEDLENGTH=true |
nchar |
DBTYPE_WSTR |
DBCOLUMNFLAGS_ISFIXEDLENGTH=false |
nvarchar |
DBTYPE_WSTR |
DBCOLUMNFLAGS_ISLONG=true或 長度上限 >4,000 個字元 或 未回報最大長度。 |
ntext |
DBTYPE_UDT |
錯誤 | |
DBTYPE_DATE |
datetime | |
DBTYPE_DBDATE
1 |
datetime (需要明確轉換) | |
DBTYPE_DBTIME |
datetime (需要明確轉換) | |
DBTYPE_DBTIMESTAMP
1 |
datetime | |
DBTYPE_ARRAY |
錯誤 | |
DBTYPE_BYREF |
忽略 | |
DBTYPE_VECTOR |
錯誤 | |
DBTYPE_RESERVED |
錯誤 |
1 指出 SQL Server 類型表示法的某種形式的轉譯,因為 SQL Server 中沒有完全對等的資料類型。 這類轉換可能會導致精度損失、溢位或下溢。 如果 SQL Server 未來版本支援對應的資料類型,則未來可以變更預設的隱含對應。
注意
numeric(p,s) 指出 SQL Server 資料類型 numeric,有效位數是 p,小數位數為 s。
DBTYPE_NUMERIC 和 DBTYPE_DECIMAL 允許的最大有效位數為 38。 建立存取子時,提供者必須支援繫結至 DBTYPE_BSTR 欄,作為 DBTYPE_WSTR。
DBTYPE_VARIANT 資料行會以 Unicode 字串 nvarchar 的形式使用。 這需要提供者支援從 DBTYPE_VARIANT 轉換成 DBTYPE_WSTR。 提供者必須依照 OLE DB 中的定義來實作這項轉換。 如需詳細資訊,請參閱 OLE DB 規格的資料類型。
解譯資料類型對應
SQL Server 類型的對應是由 OLE DB 資料類型,以及 DBCOLUMNFLAGS 描述資料行或純量值的值所決定。 在 COLUMNS 結構描述資料列集案例中,會以 DATA_TYPE 和 COLUMN_FLAGS 資料行表示這些值。 在 IColumnsInfo::GetColumnInfo 介面案例中,會以 wType 結構的 dwFlags 和 DBCOLUMNINFO 成員表示這項資訊。
若要將使用端對應用於具有特定 DBTYPE 和 DBCOLUMNFLAG 值的指定資料行,請在資料表中尋找對應的 SQL Server 類型。 運算式中遠端資料表資料行的類型規則可以使用以下簡單規則描述:
在 Transact-SQL 運算式中,指定遠端資料行值若其在資料表中相對應的 SQL Server 類型在相同情境下被視為合規,則該值為合規。
表格和規則定義:
- 比較和表達式。
一般而言,如果 X <op> <remote-column> 是資料類型 <op> 及 X 所對應資料類型的有效運算子,則 <remote-column> 是有效的運算式。
- 明確轉換。
Convert(X, <remote-column>)如果允許 of <remote-column> 對DBTYPE應至原生資料型別 Y (如上表所示),且允許從 to X 明確Y轉換。
如果使用者想要將遠端資料轉換成非預設的原生資料類型,則必須使用明確轉換。
若要在對遠端資料表執行 UPDATE 和 INSERT 陳述式時使用匯出端映對,請使用相同的資料表將原生 SQL Server 資料類型對應至 OLE DB 資料類型。 如果存在下列任一項,則允許從 SQL Server 類型 S1 對應到指定的 OLE DB 類型 T:
您可以在對應表中直接找到相應的映射。
允許隱
S1含轉換成另一個 SQL Server 類型S2,以便S2對應至對應資料表中的類型T。
大型物件 (LOB) 處理
如對應資料表所示,如果類型的 DBTYPE_STR資料行 、 DBTYPE_WSTR或 DBTYPE_BSTR 也報告 DBCOLUMNFLAGS_ISLONG,或其長度上限超過 4,000 個字元 (或未報告長度上限) ,SQL Server 會視需要將它們視為 文字 或 ntext 資料行。 同樣地,對於資料行, DBTYPE_BYTES 如果已設定,或 DBCOLUMNFLAGS_ISLONG 長度上限高於 8,000 位元組 (或未報告長度上限),資料行會被視為 影像 資料行。
text、 ntext 和 image 資料行稱為 LOB 資料行。
SQL Server 不會在 OLE DB 提供者的 LOB 上公開完整文字和影像功能。
TEXTPTRS不支援來自 OLE DB 提供者的大型物件;因此,不支援任何相關功能,例如系統TEXTPTR函數 和 READTEXT、 和 WRITETEXTUPDATETEXT 陳述式。
SELECT 支援擷取整個LOB欄的語句,以及支持遠端資料表中整個大型物件欄的 UPDATE 和 INSERT 語句。
SQL Server 可以在 LOB 資料行上使用結構化儲存介面 (如果提供者支援的話)。 結構化儲存介面依優先順序和功能遞增排序如下:ISequentialStream、Istream 或 ILockBytes。 如果支援一或多個這些介面,提供者必須在透過介面查詢IDBProperties時傳回DBPROPVAL_OO_BLOB屬性的DBPROP_OLEOBJECTS值。 此外,提供者應該指出支援它在 DBPROP_STRUCTUREDSTORAGE 屬性中支援的介面。
如果提供者不支援 LOB 資料行上的任何結構化儲存體介面,SQL Server 會自行具體化此介面,並仍將它們公開為 文字、 ntext 或 影像 資料行。
存取 LOB 資料行
如果提供者支援其中一個結構化儲存介面,SQL Server 會執行下列步驟,以在查詢執行期間擷取 LOB 資料行:
在透過
IOpenRowset::OpenRowset開啟資料列集之前,SQL Server 會先要求支援大型物件資料行上的一或多個結構化儲存介面 (ISequentialStream、Istream和ILockBytes)。 提供者支援的第一個介面是必要的;其他介面會要求為「如果便宜,則設定」,方法是將對應DBPROP結構的 dwOptions 元素設定為DBPROPOPTIONS_SETIFCHEAP。 例如,如果提供者同時支援ISequentialStream和ILockBytes,則ISequentialStream是必要的,而ILockBytes會以 "set if cheap" (若便宜即設定) 形式來要求。在開啟資料列集之後,SQL Server 會使用
IRowsetInfo::GetProperties來識別資料列集中可用的實際介面。 系統會使用提供者所傳回最後一個介面或優先順序最高的介面。 當 SQL Server 針對大型物件資料行建立存取子時,資料行會與繫結集至介面的繫結中結構的DBOBJECTiid 元素一樣DBTYPE_IUNKNOWN系結。
從 LOB 資料行讀取
使用從IRowset::GetData在資料列緩衝區中傳回的所要求結構化儲存介面的介面指標來讀取大型物件資料行。 如果提供者不支援同時開啟多個 LOB (,也就是不支援 DBPROP_MULTIPLE_STORAGEOBJECTS),而且資料列有多個大型物件資料行,SQL Server 會將 LOB 資料行複製到本機工作表。
UPDATE 和 INSERT LOB 資料行上的陳述式
SQL Server 會將新儲存物件的指標傳遞給提供者,而不是使用提供者提供的介面來修改儲存物件。 針對每個 LOB 資料行,更新或插入至儲存物件上的值會使用所選結構化儲存介面來建立。 根據它是 或UPDATEINSERT作業,儲存體物件的指標會分別透過 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 文件。
安全性
當取用者連接到 OLE DB 提供者時,除非取用者想要以整合式安全性使用者身分進行驗證,否則提供者通常需要使用者識別碼和密碼。 在分散式查詢案例中,SQL Server 可作為 OLE DB 提供者的取用者,代替 SQL Server 登入執行分散式查詢。 SQL Server 會將目前的 SQL Server 登入對應到連結伺服器上使用者識別碼和密碼。
這些對應可由指定連結伺服器的使用者指定,並可透過系統預存程序 sp_addlinkedsrvlogin 和 sp_droplinkedsrvlogin 進行設定和管理。 透過 IDBProperties::SetProperties 設定初始化群組屬性 DBPROP_AUTH_USERID 和 DBPROP_AUTH_PASSWORD,可在連接建立時,將映射決定的使用者識別碼和密碼傳遞給提供者。
當用戶端透過 Windows 驗證連接到 SQL Server 時,如果登入已使用 self 設定 sp_addlinkedsrvlogin 對應,那麼 SQL Server 在連接建立期間會嘗試模擬用戶端的安全性內容,並在提供者上設定 DBPROP_AUTH_INTEGRATED 屬性。 此程序稱為「委派」。
決定用於連接的安全性內容之後,此安全性內容的驗證,以及對資料來源中資料物件檢查該內容的權限,則完全取決於 OLE DB 提供者。
如需詳細資訊,請參閱 sp_addlinkedserver 和 sp_droplinkedsrvlogin。
查詢執行案例
評估分散式查詢時,SQL Server 會在下列一或多個案例中與 OLE DB 提供者互動:
遠端查詢
SQL Server 會產生 SQL 查詢,此查詢會評估提供者可完整評估的原始查詢部分。 此案例只能對 SQL 命令提供者進行。 SQL Server 藉由產生 SQL 查詢將作業推送至提供者的程度取決於提供者支援的 SQL 文法。 提供者應該透過下列方式指出其 SQL 支援層級:
藉由透過
DBPROP_SQLSUPPORT屬性表示 SQL 最低層級、ODBC 核心層級或 SQL-92 入門層級支援。 SQL 最低語法層級是 SQL Server 支援的新層級,可讓 SQL Server 將遠端查詢傳送給支援簡單 SQL 子集的簡單提供者。 此層級包含不SELECT包含子查詢的基本陳述式、子句中的FROM多個資料表 (因此沒有聯結) 和GROUP BY。 如需 SQL Server 針對上述每個語法層級的提供者產生遠端查詢所使用 SQL 文法子集,請參閱用於產生遠端查詢的 SQL 子集。藉由支援各種 SQL Server 特定屬性,以指出個別 SQL 功能的支援,這些功能不會包含在語法層級中,如 所報告
DBPROP_SQLSUPPORT的。 屬性清單以及 SQL Server 如何使用它們,稍後會在本節中說明。
SQL Server 使用參數化查詢執行,並以問號 (?) 作為 Transact-SQL 字串中的參數標記。 針對 SQL Server、Microsoft Jet 和 Oracle OLE DB 提供者執行參數化查詢。 針對其他提供者,如果提供者支援 ICommandWithParameters 物件, Command 且至少符合下列其中一個條件,則會使用參數化查詢執行:
提供者透過
DBPROP_SQLSUPPORT屬性指出 ODBC 核心層級的 SQL Server 支援。提供者會透過支援
IDBPPropertiesSQL Server 特定屬性,以SQLPROP_DYNCMICSQL指出對問號 (?) 參數標記的支援。 如需詳細資訊,請參閱下一節的提供者屬性。系統管理員在提供者上設定
Dynamic Parameters提供者選項來讓 SQL Server 產生參數化查詢。
當 SQL Server 產生要從遠端執行的 SQL 文字時,會使用提供者的引號字元 (透過 DBLITERAL_QUOTE 介面的 IDBInfo 常值報告) 來將資料表和資料行名稱用引號括起來。 如果不支援此常值,則不會引號表格和資料行名稱。
如果提供者支援參數化查詢執行,SQL Server 可以考慮使用參數化查詢執行策略來評估遠端資料表與本機資料表的聯結。 對從本機資料表每列生成的參數值反覆執行參數化查詢。 此策略可減少從提供者擷取的列數,而且當具有幾個列的本端表格與具有大量列的遠端表格結合時,此策略會很有用。 此遠端聯結策略可透過 REMOTE 聯結最佳化工具提示來強制執行。 如需參數化查詢執行的詳細資訊,請參閱如何:執行參數化查詢。
下列是在遠端查詢案例中對提供者執行的更高階步驟。
SQL Server 使用
Command從Session物件建立IDBCreateCommand::CreateCommand物件。如果
Remote Query Timeout伺服器設定選項設定為值 > 0,則 SQL Server 會使用DBPROP_COMMANDTIMEOUT將Command物件上的ICommandProperties::SetProperties屬性設定為相同值;必須呼叫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來釋放資料列。
遠端查詢執行感興趣的提供者屬性
如果提供者支援 中報告 DBPROP_SQLSUPPORT的語法層級未涵蓋的 SQL 功能,則可以使用各種提供者特定的屬性來指出它們。
SQLPROP_GROUPBY。 此屬性對於支援 SQL 最低層級的提供者很重要。 此屬性表示提供者支援陳述式中的SELECTandGROUP BYHAVING子句。 此外,此屬性也表示提供者支援下列五個匯總函式MIN、MAX、SUMCOUNT和AVG。 提供者可能不支援DISTINCT這些匯總函式的引數。SQLPROP_SUBQUERIES。 此屬性對於支援 SQL 最低層級的提供者很重要。 它指出提供者支援子查詢,如 SQL-92 入門層級所指定。 這包括SELECT清單和WHERE子句中的子查詢,並支援相互關聯子查詢的IN、EXISTS、ALL和ANY運算子。SQLPROP_DATELITERALS。 此屬性對於任何提供者 (包括支援 SQL-92 入門層級的提供者) 都很重要。 對日期時間常值標準常值語法的支援不是 SQL-92 進入層級的一部分。 此 SQL Server 特定屬性指出提供者支援日期時間常值語法 (如 SQL-92 標準所指定)。SQLPROP_ANSILIKE。 對於支援 SQL 最低層級的提供者很重要。 此內容指出提供者根據LIKESQL-92 進入層次 ('%'和'_'萬用字元) 支援運算子。 這對於支援 SQL-Minimum 層級的提供者很有用,因為 SQL-Minimum 層級不包含LIKE支援。SQLPROP_INNERJOIN。 此屬性對於支援 SQL 最低層級的提供者很重要。 它表示支援FROM子句中的多個資料表。 這對於僅支援 SQL-Minimum 層級的提供者很有用,因為 SQL-Minimum 層級不包含聯結的支援。 這並不表示支援明確JOIN的關鍵字,也不表示OUTER支援聯結。 它指出只支援透過FROM子句中的資料表清單進行隱含聯結。SQLPROP_DYNAMICSQL。 指出支援?作為參數標記。 在WHERE子句或SELECT清單中,純量項目的位置應支援參數標記。?參數標記支援可讓 SQL Server 將參數化查詢傳送給提供者。SQLPROP_NESTEDQUERIES。 表示子句中巢狀SELECTs 的支援 (例如,SELECT * FROM (SELECT * FROM T)).FROM在許多情況下,當 SQL Server 產生要從遠端執行的查詢字串時,會在查詢的SELECT子句中使用巢狀FROM陳述式。 由於 SQL-92 進入層級不需要巢狀SELECT支援,因此除非提供者也設定此屬性,否則 SQL Server 不會將具有巢狀SELECT陳述式的查詢委派給提供者。 或者,系統管理員也可以為提供者設定Nested Queries提供者選項,讓 SQL Server 對提供者產生巢狀查詢。
提供者可以使用稱為 SQLPROPSET_OPTHINTS 的 SQL Server 特定屬性集來支援這些屬性,並具有定義的 PROPID 值。 使用下列常數來定義屬性集 SQLPROPSET_OPTHINTS 和兩個屬性:
extern const GUID SQLPROPSET_OPTHINTS = { 0x2344480c, 0x33a7, 0x11d1, { 0x9b, 0x1a, 0x0, 0x60, 0x8, 0x26, 0x8b, 0x9e } };
enum SQLPROPERTIES {
SQLPROP_NESTEDQUERIES = 0x4,
SQLPROP_DYNAMICSQL = 0x5,
SQLPROP_GROUPBY = 0x6,
SQLPROP_DATELITERALS = 0x7,
SQLPROP_ANSILIKE = 0x8,
SQLPROP_INNERJOIN = 0x9,
SQLPROP_SUBQUERIES = 0x10
};
字元集及排序順序含意
SQL Server 支援在每個資料行層級指定字元資料的定序。 對照包括非 Unicode 字元資料 (char 和 varchar 直欄) 的字集及排序順序規格。 針對 Unicode 資料 (nchar 和 nvarchar 資料行) ,定序只會指定排序順序。
只有在連結伺服器所使用的字元集 (適用於非 Unicode 資料)、排序次序和字串比較語意與本機伺服器所使用的字元集相同時,SQL Server 才會將字串比較委派給提供者。
在 SQL Server 連結的伺服器案例中,SQL Server 會自動判斷定序相容性。 針對其他提供者,系統管理員必須向 SQL Server 指出字元資料定序來自指定的連結伺服器。 在 SQL Server 中,支援稱為 [Collation Name] 的新連結伺服器選項。 如果系統管理員判斷鏈接伺服器採用的定序語意與其中一個 SQL Server 標準定序相同,則可以將 Collation Name 選項設定為該定序名稱。 您可以使用系統預存程序 Collation Name 來設定 sp_serveroption 選項。 只有在同時符合下列兩個條件時,才應該設定此選項:
遠端排序次序和字元集與指定的 SQL Server 定序相同。
OLE DB 提供者所使用的字串比較語意遵循 SQL-92 標準規格語意,或相當於 SQL Server 的比較語意。
為了向後相容,仍然支援 SQL Server 7.0 中引入的「定序相容」選項。 將其設定為 true 相當於將 [定序名稱] 選項設定為 SQL Server 資料庫的 master 預設定序。 新的應用程式應該使用 [定序名稱] 選項,而不是 [定序相容] 選項。
索引存取
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開啟的資料列集。提供者必須在透過
IRowsetLocate開啟的資料列集上支援IRowsetChange和IOpenRowset介面,才能更新或刪除資料表。IRowsetChange介面必須支援更新 (SetData) 和刪除 (DeleteRows) 方法。如果提供者不支援
ITransactionLocal,UPDATEDELETE且只有在為該提供者設定選項,且陳述式不在使用者交易中時Non-transacted,才允許陳述式。如果提供者不支援
ITransactionJoin,則只有在使用者交易中不允許 orUPDATEDELETE陳述式。
針對已更新資料表開啟的資料列集上需要下列資料列集屬性: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用於刪除作業,以執行對符合條件的數據列所需的變更。
INSERT 陳述
支援遠端資料表中的 INSERT 語句的條件比 UPDATE 和 DELETE 語句更寬鬆:
提供者必須在基底資料表上開啟的資料列集上支援
IRowsetChange::InsertRow,才能插入資料列集。如果提供者不支援
ITransactionLocal,INSERT只有在為該連結伺服器設定選項,且陳述式不在使用者交易中時Non-transacted updates,才允許陳述式。如果提供者不支援
ITransactionJoin,INSERT則只有在陳述式不在使用者交易中時才允許陳述式。
SQL Server 使用 IOpenRowset::OpenRowset 在基底資料表上開啟資料列集,並呼叫 IRowsetChange::InsertRow 將新的資料列插入基底資料列集。
傳遞查詢
此案例類似於遠端查詢中的案例,不同之處 ICommand 在於提供給的命令文字是使用者提交的命令字串,而且不會由 SQL Server 解譯。 當 SQL Server 呼叫 DBGUID_DEFAULT 時,會使用 ICommandText::SetCommandText 作為方言識別碼。
DBGUID_DEFAULT 指出提供者應該使用其預設方言。 如果此命令文字傳回多個結果集 (例如,如果命令叫用傳回多個結果集的預存程序),則 SQL Server 只會使用命令中的第一個結果集。
如需 SQL Server 使用的所有 OLE DB 介面清單,請參閱 SQL Server 使用的 OLE DB 介面。
結論
Microsoft SQL Server 提供最強大的工具組,可從異質性資料來源存取資料。 藉由了解 SQL Server 所公開的 OLE-DB 介面,開發人員就可以在分散式查詢中進行高度的控制和複雜度。
SQL Server 所取用的 OLE 資料庫介面
下表列出 SQL Server 使用的所有 OLE DB 介面。 [必要] 資料行會指出介面是否屬於 SQL Server 所需的最低限度 OLE DB 功能的一部分,或是否為選擇性。 如果指定的介面未標示為必要,SQL Server 仍可存取提供者,但無法針對提供者進行某些特定的 SQL Server 功能或優化。
在選擇性介面案例中,[案例] 欄指出使用指定介面的六個案例其中一或多個案例。 例如, IRowsetChange 基底資料表資料列集上的介面是選擇性介面;此介面用於 UPDATE and DELETE 陳述式和 INSERT 陳述式案例。 如果不支援此介面, UPDATE則無法支援該提供者的 、 DELETE和 INSERT 陳述式。 其他選擇性介面會在 [案例] 資料行中標示為「效能」,表示此介面會產生更好的整體效能。 例如,如果不支援介面,SQL IDBSchemaRowset Server 必須開啟資料列集兩次:一次用於其中繼資料,一次用於查詢執行。 藉由支援 IDBSchemaRowset,即可改善 SQL Server 效能。
| 物件 | 介面 | 必要 | 註解 | 情境 |
|---|---|---|---|---|
| 資料來源物件 | IDBInitialize |
是 | 初始化與設定資料和安全性內容。 | |
IDBCreateSession |
是 | 建立 DB Session 物件。 | ||
IDBProperties |
是 | 取得提供者功能的相關資訊、設定初始化屬性、必要屬性: DBPROP_INIT_TIMEOUT。 |
||
IDBInfo |
否 | 取得引號常值、目錄、名稱、部分、分隔符號、字元等。 | 遠端查詢。 | |
| DB Session 物件 | IDBSchemaRowset |
否 | 取得資料表/資料行中繼資料。 所需的資料列集:TABLES、COLUMNS、PROVIDER_TYPES;其他使用的資料列集 (如果可用):INDEXES、TABLE_STATISTICS。 |
效能、索引存取。 |
IOpenRowset |
是 | 在資料表、索引或直方圖上開啟資料列集。 | ||
IGetDataSource |
是 | 用於從資料庫會話對象返回至DSO。 | ||
IDBCreateCommand |
否 | 用於為支援查詢的提供者建立查詢命令物件。 | 遠端查詢、直通查詢。 | |
ITransactionLocal |
否 | 用於已完成交易的更新。 |
UPDATE 和 DELETE、INSERT 陳述式。 |
|
ITransactionJoin |
否 | 用於分散式交易支援。 |
UPDATE 和 DELETE、INSERT 陳述式 (如果在使用者交易中)。 |
|
| Rowset 物件 | IRowset |
是 | 掃描列。 | |
IAccessor |
是 | 將資料行繫結至資料列集。 | ||
IColumnsInfo |
是 | 取得資料列集的資料行相關資訊。 | ||
IRowsetInfo |
是 | 取得資料列集屬性的相關資訊。 | ||
IRowsetLocate |
否 | 在 UPDATE/DELETE 作業中,進行索引查閱是必要的;用於透過書籤查閱資料列。 |
索引存取、 UPDATE和 DELETE 陳述式。 |
|
IRowsetChange |
否 | 對於在資料列集上執行 INSERTS/UPDATES/ DELETES 是必要的。 基底資料表的資料列集應該支援 、 UPDATE和DELETE陳述式的INSERT此介面。 |
UPDATE 和 DELETE、INSERT 陳述式。 |
|
IConvertType |
是 | 用於確認資料列集是否支援其資料行的特定資料類型轉換。 | ||
| 索引 | IRowset |
是 | 掃描列。 | 索引存取、效能。 |
IAccessor |
是 | 將資料行繫結至資料列集。 | 索引存取、效能。 | |
IColumnsInfo |
是 | 取得資料列集的資料行相關資訊。 | 索引存取、效能。 | |
IRowsetInfo |
是 | 取得資料列集屬性的相關資訊。 | 索引存取、效能。 | |
IRowsetIndex |
是 | 對於索引上的資料列集是必要的;用於索引功能 (設定範圍、搜尋)。 | 索引存取、效能。 | |
| 指令 | ICommand |
是 | 遠端查詢、直通查詢。 | |
ICommandText |
是 | 用於定義查詢文字。 | 遠端查詢、直通查詢。 | |
IColumnsInfo |
是 | 用於取得查詢結果的資料行中繼資料。 | 遠端查詢、直通查詢。 | |
ICommandProperties |
是 | 用於指定命令所傳回資料列集的必要屬性。 | 遠端查詢、直通查詢。 | |
ICommandWithParameters |
否 | 用於將查詢執行參數化。 | 遠端查詢、效能。 | |
ICommandPrepare |
否 | 用於準備命令以取得中繼資料 (如果可用,則用於傳遞查詢)。 | 遠端查詢、效能。 | |
| 錯誤對象 | IErrorRecords |
是 | 用於取得與單一錯誤記錄對應的 IErrorInfo 介面指標。 |
|
IErrorInfo |
是 | 用於取得與單一錯誤記錄對應的 IErrorInfo 介面指標。 |
||
| 任何物件 | ISupportErrorInfo |
否 | 用於確認指定的介面是否支援錯誤物件。 |
注意
Index object、 Command object 和 Error object 不是必要項目。 不過,如果支援,則列出的介面是必要,如 [必要] 資料行中所指定。
用於產生遠端查詢的 SQL 子集
SQL Server 查詢處理器針對 SQL 命令提供者產生的 SQL 子集,取決於提供者依照 DBPROP_SQLSUPPORT 屬性指定支援的語法層級。
支援 SQL 入門層級或 ODBC 核心層級的 SQL 命令提供者
SQL Server 會針對支援 SQL-92 入門層級或 ODBC 核心層級的 SQL 命令提供者所評估查詢,使用下列 SQL 語言子集:
SELECT陳述式搭配SELECT、FROM、WHERE、GROUP BY、UNION、UNION ALL、ORDER BY DESC、ASC和HAVING子句。UNION和UNION ALL只會針對支援 SQL-92 入門層級的提供者產生,而不會針對支援 ODBC 核心層級的提供者產生。SELECT子句:-
SELECT清單中的純量子查詢。 - 不含
AS關鍵字的資料行別名。
-
FROM子句:不會使用明確的聯結關鍵字;逗號分隔的資料表名稱可用來指定內部聯結,而外部聯結不會在遠端查詢中指定。
表單的巢狀查詢
FROM(<nested query>)<alias>。不含 AS 關鍵字的資料表別名。
WHERE子句使用子查詢搭配NOTEXISTS、ANY、ALL。表達式
使用的彙總函式:
MIN([DISTINCT])、MAX([DISTINCT])、COUNT([DISTINCT])、SUM([DISTINCT])、AVG([DISTINCT])和COUNT(*)。比較運算子:
<、=、<=、>、<>、>=、IS NULL和IS NOT NULL。布林運算子:
AND、OR和NOT。算術運算子:
+、-、*和/。
常數:
- 數值和貨幣字面值總是會以
( )括住。 - 字元常值會以
' '括起。
- 數值和貨幣字面值總是會以
支援 SQL 最低層級的 SQL 命令提供者
針對支援 SQL 最低層級的 SQL 命令提供者,SQL Server 會使用下列文法來產生 SQL。
此文法是使用 ODBC 3.0 中所述的 SQL 最低層級文法衍生而來。 此文法中的所有差異都會醒目提示。 以 *bold italics* 顯示的項目是 ODBC 3.0 中所述 SQL 最低層級文法中新增項目。 以綠色顯示已刪除項目是從此文法中移除的項目。
<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 <order_by_clause>
<order_by_clause> ::= ORDER BY <sort_specification> [ , <sort_specification> ] ...
<sort_specification> ::= { | column_name } [ ASC | DESC ]
常見的語法元素
<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 ::= .
<character> 是驅動程式/資料來源字元集中的任何字元。 若要在 <character_string_literal>中包含單一文字引號字元 (') ,請使用兩個文字引號字元 ('')。
SQL Server 特定屬性
enum SQLPROPERTIES
{
SQLPROP_NOHPNEEDED = 0x1,
SQLPROP_FREETHREADED = 0x2,
SQLPROP_UMSENABLED = 0x3,
SQLPROP_NESTEDQUERIES = 0x4,
SQLPROP_DYNAMICSQL = 0x5,
SQLPROP_GROUPBY = 0x6,
SQLPROP_DATELITERALS = 0x7,
SQLPROP_ANSILIKE = 0x8,
SQLPROP_INNERJOIN = 0x9,
SQLPROP_SUBQUERIES = 0x10,
SQLPROP_PARALLELSCAN = 0x11,
SQLPROP_COLUMNCOLLATION = 0x12,
SQLPROP_CARDINALITY = 0x13,
SQLPROP_SIMPLEUPDATES = 0x14,
SQLPROP_SQLLIKE = 0x15,
SQLPROP_BITREMOTING = 0x16,
SQLPROP_UNICODELITERALS = 0x17,
SQLPROP_USELATESTCOLLATIONVERSION = 0x18
};