共用方式為


TN045:Long Varchar/Varbinary 的 MFC/資料庫支援

注意

下列技術提示自其納入線上文件以來,未曾更新。 因此,有些程序和主題可能已過期或不正確。 如需最新資訊,建議您在線上文件索引中搜尋相關的主題。

此附注說明如何使用 MFC 資料庫類別來擷取 和傳送 ODBC SQL_LONGVARCHAR和 SQL_LONGVARBINARY 資料類型。

Long Varchar/Varbinary 支援概觀

ODBC SQL_LONG_VARCHAR SQL_LONGBINARY 資料類型(這裡稱為資料行長)可以保存大量資料。 有 3 種方式可以處理此資料:

  • 將它系結至 CString / CByteArray

  • 將它系結至 CLongBinary

  • 請勿完全系結並擷取並手動傳送長資料值,與資料庫類別無關。

這三種方法中的每一個都有優點和缺點。

查詢的參數不支援長資料行。 它們僅支援 outputColumns。

將長資料行系結至 CString/CByteArray

優點:

這種方法很容易理解,而且您可以使用熟悉的類別。 架構支援 CFormView CStringDDX_Text 。 您有許多具有 CStringCByteArray 類別的一般字串或集合功能,而且您可以控制在本機配置的記憶體數量,以保存資料值。 架構會在 或 AddNew 函式呼叫期間 Edit 維護欄位資料的舊複本,而且架構可以自動偵測資料的變更。

注意

由於 CString 設計用於處理字元資料,以及 CByteArray 處理二進位資料,因此建議您將字元資料 (SQL_LONGVARCHAR) CString 放入 ,並將二進位資料 ( SQL_LONGVARBINARY ) 放入 CByteArray

CByteArray 的 RFX 函 CString 式具有額外的引數,可讓您覆寫已配置記憶體的預設大小,以保存資料行的擷取值。 請注意下列函式宣告中的 nMaxLength 引數:

void AFXAPI RFX_Text(CFieldExchange* pFX,
    const char *szName,
    CString& value,
    int nMaxLength = 255,
    int nColumnType =
    SQL_VARCHAR);

void AFXAPI RFX_Binary(CFieldExchange* pFX,
    const char *szName,
    CByteArray& value,
    int nMaxLength = 255);

如果您將長資料行擷取至 CStringCByteArray ,則傳回的資料量上限預設為 255 個位元組。 超過此專案的任何專案會被忽略。 在此情況下,架構會擲回例外 狀況AFX_SQL_ERROR_DATA_TRUNCATED 。 幸運的是,您可以明確地將 nMaxLength 增加為更大的值,最多增加 MAXINT

注意

MFC 會使用 nMaxLength 的值來設定函 SQLBindColumn 式的本機緩衝區。 這是儲存資料的本機緩衝區,實際上不會影響 ODBC 驅動程式所傳回的資料量。 RFX_TextRFX_Binary 只使用 進行一次呼叫 SQLFetch ,以從後端資料庫擷取資料。 每個 ODBC 驅動程式在單一擷取中可以傳回的資料量有不同的限制。 此限制可能遠小於 nMaxLength 中設定的值,在此情況下,將會擲回例外 狀況AFX_SQL_ERROR_DATA_TRUNCATED 。 在這些情況下,切換至 using RFX_LongBinary 而非 RFX_TextRFX_Binary 以便擷取所有資料。

ClassWizard 會將SQL_LONGVARCHAR 系結至 CString ,或 為您系 SQL_LONGVARBINARY CByteArray 。 如果您想要配置超過 255 個位元組,以擷取長資料行,則可以為 nMaxLength 提供明確的值。

當長資料行系結至 或 CByteArray 時,更新欄位的運作方式與系結至 CString SQL_ VARCHAR 或 SQL_ VARBINARY 時相同。 在 期間 Edit ,系統會快取資料值,並在呼叫 時 Update 進行比較,以偵測資料值的變更,並適當地設定資料行的 Dirty 和 Null 值。

將長資料行系結至 CLongBinary

如果您的長資料行可能包含更多 MAXINT 位元組的資料,您應該考慮將它擷取到 CLongBinary

優點:

這會擷取整個長資料行,最多可擷取可用的記憶體。

缺點:

資料會保留在記憶體中。 這種方法對於非常大量的資料來說也非常昂貴。 您必須呼叫 SetFieldDirty 系結的資料成員,以確保欄位包含在作業中 Update

如果您將長資料行擷取到 CLongBinary ,資料庫類別會檢查完整資料行的大小總計,然後配置 HGLOBAL 足夠大的記憶體區段來保存整個資料值。 然後,資料庫類別會將整個資料值擷取到配置的 HGLOBAL 中。

如果資料來源無法傳回長資料行的預期大小,架構會擲回例外 狀況AFX_SQL_ERROR_SQL_NO_TOTAL 。 如果嘗試配置 HGLOBAL 失敗,則會擲回標準記憶體例外狀況。

ClassWizard 會為您系結 SQL_LONGVARCHAR SQL_LONGVARBINARY CLongBinary 選取 CLongBinary 為 [新增成員變數] 對話方塊中的 [變數類型]。 ClassWizard 接著會將呼叫新增 RFX_LongBinary 至您的 DoFieldExchange 呼叫,並將系結欄位總數遞增。

若要更新長資料行值,請先在 的 m_hData 成員上呼叫 ::GlobalSize ,確定已 HGLOBAL 配置的資料夠大,以保存新的資料。 CLongBinary 如果太小,請釋放 HGLOBAL 並配置適當的大小。 然後設定 m_dwDataLength 以反映新的大小。

否則,如果 m_dwDataLength 大於您要取代的資料大小,您可以釋放並重新配置 HGLOBAL ,或讓它保持配置。 請務必指出實際用於m_dwDataLength 位元組數目。

更新 CLongBinary 的運作方式

您不需要瞭解更新 CLongBinary 的運作方式,但如果您選擇下列第三種方法,將長資料值傳送至資料來源的範例可能很有用。

注意

若要在 CLongBinary 更新中包含欄位,您必須明確呼叫 SetFieldDirty 欄位。 如果您對欄位進行任何變更,包括將它設定為 Null,您必須呼叫 SetFieldDirty 。 您也必須呼叫 SetFieldNull ,第二個參數為 FALSE ,才能將欄位標示為具有值。

更新 CLongBinary 欄位時,資料庫類別會使用 ODBC 的 DATA_AT_EXEC 機制(請參閱 's rgbValue 引數的 ODBC 檔 SQLSetPos )。 當架構準備插入或更新語句,而不是指向 HGLOBAL 包含資料的 時, CLongBinary 位址 會改為設定為數據行的值 ,並將長度指標設定為 SQL_DATA_AT_EXEC 。 稍後,當 update 語句傳送至資料來源時, SQLExecDirect 會傳回 SQL_NEED_DATA 。 這會警示架構,指出此資料行之參數的值實際上是 的 CLongBinary 位址。 架構會使用小型緩衝區呼叫 SQLGetData 一次,預期驅動程式會傳回資料的實際長度。 如果驅動程式傳回二進位大型物件的實際長度(BLOB),MFC 會視需要重新配置空間來擷取 BLOB。 如果資料來源傳 回SQL_NO_TOTAL ,表示無法判斷 BLOB 的大小,MFC 將會建立較小的區塊。 預設的初始大小為 64K,後續區塊會是大小兩倍;例如,第二個會是 128K、第三個是 256K 等等。 初始大小可設定。

未系結:使用 SQLGetData 直接從 ODBC 擷取/傳送資料

使用此方法時,您會完全略過資料庫類別,並自行處理長資料行。

優點:

您可以視需要將資料快取至磁片,或以動態方式決定要擷取的資料量。

缺點:

您沒有取得架構或 Edit AddNew 支援,而且您必須自行撰寫程式碼來執行基本功能( Delete 不過可以運作,因為它不是資料行層級作業)。

在此情況下,長資料行必須位於記錄集的選取清單中,但不應由架構系結。 若要這樣做,其中一個方法是透過 或 作為 lpszSQL 引數提供您自己的 SQL 語句 GetDefaultSQLCRecordsetOpen 函式,而不是將額外的資料行與RFX_函式呼叫系結。 ODBC 要求未系結的欄位出現在系結欄位的右邊,因此請將未系結的資料行或資料行新增至選取清單的結尾。

注意

因為您的長資料行未受架構約束,所以不會使用 CRecordset::Update 呼叫來處理對它的變更。 您必須自行建立並傳送必要的 SQL INSERT UPDATE 語句。

另請參閱

依編號顯示的技術提示
依分類區分的技術提示