SQL Server 2005 在存取 Database Engine 的應用程式中引進了對多個使用中結果集 (MARS) 的支援。 在舊版 SQL Server 中,資料庫應用程式無法在連接上維護多個作用中語句。 使用 SQL Server 預設結果集時,應用程式必須先處理或取消一個批次的所有結果集,才能在該連線上執行任何其他批次。 SQL Server 2005 引進了新的連接屬性,可讓應用程式針對每個連線有多個擱置要求,特別是每個連線有多個作用中的默認結果集。
MARS 使用下列新功能簡化應用程式設計:
應用程式可以開啟多個默認結果集,並可交錯讀取它們。
應用程式可以在開啟默認結果集時執行其他語句(例如 INSERT、UPDATE、DELETE 和預存過程調用)。
使用MARS的應用程式會發現下列指導方針很有説明:
默認結果集應該用於單一 SQL 語句所產生的短期或簡短結果集(SELECT、DML 與 OUTPUT、RECEIVE、READ TEXT 等等)。
伺服器數據指標應該用於單一 SQL 語句所產生的較長壽命或大型結果集。
不論其是否傳回結果,以及傳回多個結果的批次,一律讀取至程式要求的結果結尾。
盡可能使用 API 呼叫來變更連接屬性,並優先管理交易,以 Transact-SQL 語句。
在MARS中,並行批次執行時禁止會話範圍的模擬。
備註
根據預設,不會啟用MARS功能。 若要使用 SQL Server Native Client 連線到 SQL Server 時使用 MARS,您必須在連接字串中特別啟用它。 如需詳細資訊,請參閱本主題稍後的 SQL Server Native Client OLE DB 提供者和 SQL Server Native Client ODBC 驅動程式小節。
SQL Server Native Client 不會限制連接的作用中語句數目。
不需要同時執行的單一多重語句批次或預存程式的典型應用程式將受益於MARS,而不需要瞭解MARS的實作方式。 不過,具有更複雜需求的應用程式確實需要考慮到這一點。
MARS 可讓您在單一連線內交錯執行多個要求。 也就是說,它允許批次執行,並在其執行中,允許執行其他要求。 不過請注意,MARS 是以交錯方式定義,而不是在平行執行方面。
MARS 基礎結構可讓多個批次以交錯方式執行,不過執行只能在定義完善的點切換。 此外,大部分語句必須在批次內以不可部分完成的方式執行。 將數據列傳回至用戶端的語句,有時稱為 產生點,可在數據列傳送至用戶端之前交錯執行,例如:
選擇
擷取
收到
在預存程式或批次中執行的任何其他語句都必須執行到完成,才能將執行切換至其他MARS要求。
批次交錯執行的確切方式會受到許多因素的影響,而且很難預測包含產生點之多個批次的命令執行確切順序。 請小心避免不必要的副作用,因為交錯執行這類複雜批次。
避免使用 API 呼叫而非 Transact-SQL 語句來管理連接狀態 (SET、 USE) 和交易 (BEGIN TRAN, COMMIT, ROLLBACK) 的問題,方法是不要將這些語句包含在同時包含產生點的多語句批次中,以及藉由取用或取消所有結果來串行化執行這類批次。
備註
啟用MARS時啟動手動或隱含交易的批次或預存程式,必須在批次結束之前完成交易。 如果沒有,SQL Server 會在批次完成時回復交易所做的所有變更。 這類交易是由 SQL Server 以批次範圍交易來管理。 這是 SQL Server 2005 中引進的新交易類型,可啟用啟用 MARS 啟用時要使用的現有良好行為預存程式。 如需批次範圍交易的詳細資訊,請參閱交易語句(Transact-SQL)。
如需從 ADO 使用 MARS 的範例,請參閱 搭配 SQL Server Native Client 使用 ADO。
SQL Server Native Client OLE DB 提供者
SQL Server Native Client OLE DB 提供者透過新增SSPROP_INIT_MARSCONNECTION數據源初始化屬性,在DBPROPSET_SQLSERVERDBINIT屬性集中實作,以支援MARS。 此外,已加入新的連接字串關鍵字 MarsConn, 。 它會接受 true 或 false 值; false 是預設值。
數據源屬性DBPROP_MULTIPLECONNECTIONS預設為 VARIANT_TRUE。 這表示提供者會繁衍多個連接,以支援多個並行命令和數據列集物件。 啟用MARS時,SQL Server Native Client 可以在單一連線上支援多個命令和數據列集物件,因此預設會將MULTIPLE_CONNECTIONS設定為VARIANT_FALSE。
如需DBPROPSET_SQLSERVERDBINIT屬性集之增強功能的詳細資訊,請參閱 初始化和授權屬性。
SQL Server Native Client OLE DB 提供者範例
在此範例中,數據源物件是使用 SQL Server Native OLE DB 提供者建立,而 MARS 是在建立會話物件之前,使用設定的 DBPROPSET_SQLSERVERDBINIT 屬性來啟用。
#include <sqlncli.h>
IDBInitialize *pIDBInitialize = NULL;
IDBCreateSession *pIDBCreateSession = NULL;
IDBProperties *pIDBProperties = NULL;
// Create the data source object.
hr = CoCreateInstance(CLSID_SQLNCLI10, NULL,
CLSCTX_INPROC_SERVER,
IID_IDBInitialize,
(void**)&pIDBInitialize);
hr = pIDBInitialize->QueryInterface(IID_IDBProperties, (void**)&pIDBProperties);
// Set the MARS property.
DBPROP rgPropMARS;
// The following is necessary since MARS is off by default.
rgPropMARS.dwPropertyID = SSPROP_INIT_MARSCONNECTION;
rgPropMARS.dwOptions = DBPROPOPTIONS_REQUIRED;
rgPropMARS.dwStatus = DBPROPSTATUS_OK;
rgPropMARS.colid = DB_NULLID;
V_VT(&(rgPropMARS.vValue)) = VT_BOOL;
V_BOOL(&(rgPropMARS.vValue)) = VARIANT_TRUE;
// Create the structure containing the properties.
DBPROPSET PropSet;
PropSet.rgProperties = &rgPropMARS;
PropSet.cProperties = 1;
PropSet.guidPropertySet = DBPROPSET_SQLSERVERDBINIT;
// Get an IDBProperties pointer and set the initialization properties.
pIDBProperties->SetProperties(1, &PropSet);
pIDBProperties->Release();
// Initialize the data source object.
hr = pIDBInitialize->Initialize();
//Create a session object from a data source object.
IOpenRowset * pIOpenRowset = NULL;
hr = IDBInitialize->QueryInterface(IID_IDBCreateSession, (void**)&pIDBCreateSession));
hr = pIDBCreateSession->CreateSession(
NULL, // pUnkOuter
IID_IOpenRowset, // riid
&pIOpenRowset )); // ppSession
// Create a rowset with a firehose mode cursor.
IRowset *pIRowset = NULL;
DBPROP rgRowsetProperties[2];
// To get a firehose mode cursor request a
// forward only read only rowset.
rgRowsetProperties[0].dwPropertyID = DBPROP_IRowsetLocate;
rgRowsetProperties[0].dwOptions = DBPROPOPTIONS_REQUIRED;
rgRowsetProperties[0].dwStatus = DBPROPSTATUS_OK;
rgRowsetProperties[0].colid = DB_NULLID;
VariantInit(&(rgRowsetProperties[0].vValue));
rgRowsetProperties[0].vValue.vt = VARIANT_BOOL;
rgRowsetProperties[0].vValue.boolVal = VARIANT_FALSE;
rgRowsetProperties[1].dwPropertyID = DBPROP_IRowsetChange;
rgRowsetProperties[1].dwOptions = DBPROPOPTIONS_REQUIRED;
rgRowsetProperties[1].dwStatus = DBPROPSTATUS_OK;
rgRowsetProperties[1].colid = DB_NULLID;
VariantInit(&(rgRowsetProperties[1].vValue));
rgRowsetProperties[1].vValue.vt = VARIANT_BOOL;
rgRowsetProperties[1].vValue.boolVal = VARIANT_FALSE;
DBPROPSET rgRowsetPropSet[1];
rgRowsetPropSet[0].rgProperties = rgRowsetProperties
rgRowsetPropSet[0].cProperties = 2
rgRowsetPropSet[0].guidPropertySet = DBPROPSET_ROWSET;
hr = pIOpenRowset->OpenRowset (NULL,
&TableID,
NULL,
IID_IRowset,
1,
rgRowsetPropSet
(IUnknown**)&pIRowset);
SQL Server Native Client ODBC Driver
SQL Server Native Client ODBC 驅動程式透過新增 SQLSetConnectAttr 和 SQLGetConnectAttr 函式,支援 MARS。 已新增SQL_COPT_SS_MARS_ENABLED以接受SQL_MARS_ENABLED_YES或SQL_MARS_ENABLED_NO,SQL_MARS_ENABLED_NO為預設值。 此外,已加入新的連接字串關鍵字 Mars_Connection, 。 它接受 「yes」 或 「no」 值;“no” 是預設值。
SQL Server Native Client ODBC 驅動程式範例
在此範例中,會先使用 SQLSetConnectAttr 函式來啟用 MARS,再呼叫 SQLDriverConnect 函式來連接資料庫。 建立連接之後,會呼叫兩個 SQLExecDirect 函式,以在相同的連接上建立兩個不同的結果集。
#include <sqlncli.h>
SQLSetConnectAttr(hdbc, SQL_COPT_SS_MARS_ENABLED, SQL_MARS_ENABLED_YES, SQL_IS_UINTEGER);
SQLDriverConnect(hdbc, hwnd,
"DRIVER=SQL Server Native Client 10.0;
SERVER=(local);trusted_connection=yes;", SQL_NTS, szOutConn,
MAX_CONN_OUT, &cbOutConn, SQL_DRIVER_COMPLETE);
SQLAllocHandle(SQL_HANDLE_STMT, hdbc, &hstmt1);
SQLAllocHandle(SQL_HANDLE_STMT, hdbc, &hstmt2);
// The 2nd execute would have failed with connection busy error if
// MARS were not enabled.
SQLExecDirect(hstmt1, L"SELECT * FROM Authors", SQL_NTS);
SQLExecDirect(hstmt2, L"SELECT * FROM Titles", SQL_NTS);
// Result set processing can interleave.
SQLFetch(hstmt1);
SQLFetch(hstmt2);