天天看點

DB2 9 使用斥地(733 考試)認證指南,第 5 局部: CLI/ODBC 程式設計(3)

,機關CLI/ODBC使用遞次,CLI/ODBC使用遞次的構成局部,全部CLI/ODBC使用遞次都要被機關來執行以下三個分譬喻的任務:,初始化,事件處理,制止,每個任務觸及到的任務是議決挪用一個或多

DB2 9 使用斥地(733 考試)認證指南,第 5 局部: CLI/ODBC 程式設計(3)
DB2 9 使用斥地(733 考試)認證指南,第 5 局部: CLI/ODBC 程式設計(3)
DB2 9 使用斥地(733 考試)認證指南,第 5 局部: CLI/ODBC 程式設計(3)
DB2 9 使用斥地(733 考試)認證指南,第 5 局部: CLI/ODBC 程式設計(3)

機關 CLI/ODBC 使用遞次

CLI/ODBC 使用遞次的構成局部

全部 CLI/ODBC 使用遞次都要被機關來執行以下三個分譬喻的任務:

  • 初始化
  • 事件處理
  • 制止

每個任務觸及到的任務是議決挪用一個或多個 CLI/ODBC API 函數來完成的。用于完成這些任務的良多 CLI/ODBC 函數必須依照特定的遞次來挪用,不然會産生發火錯誤。圖 1 标出了用于執行初始化和制止任務的一些根底的 CLI/ODBC 函數:

圖 1. CLI/ODBC 使用遞次執行的根底任務
DB2 9 使用斥地(733 考試)認證指南,第 5 局部: CLI/ODBC 程式設計(3)

CLI/ODBC 使用遞次還可以執行圖 1 中列出的 3 個任務以外的任務,比方錯誤處理和動态處理。在前面的小節 診斷和錯誤處理 中,可以看到 CLI/ODBC 使用遞次中如何處理錯誤。

DB2 9 使用斥地(733 考試)認證指南,第 5 局部: CLI/ODBC 程式設計(3)
DB2 9 使用斥地(733 考試)認證指南,第 5 局部: CLI/ODBC 程式設計(3)
DB2 9 使用斥地(733 考試)認證指南,第 5 局部: CLI/ODBC 程式設計(3)
DB2 9 使用斥地(733 考試)認證指南,第 5 局部: CLI/ODBC 程式設計(3)
回頁首

分派本錢

在初始化期間,須要分派(和初始化)處理事件所需的本錢,并建樹到事件處理任務須要使用的資料源的鄰接。CLI/ODBC 使用遞次使用的本錢由議決專注句柄辨別的公用資料存儲區構成。(句柄是一個簡樸的指針變量,它指向 DB2 CLI 或 ODBC Driver Manager 所節制的資料對象,該資料對象由 CLI/ODBC 函數挪用援用。)議決使用資料存儲區和句柄,CLI/ODBC 使用遞次不用擔任分派和經管全局變量和諸如嵌入式 SQL 使用遞次中使用的 SQLCA 和 SQLDA 之類的資料機關。有四種分譬喻典範的句柄:

  • 環境句柄: 指向一個資料存儲區的指針,該資料存儲區搜羅特定于 CLI/ODBC 的全局資訊。
  • 鄰接句柄: 指向一個資料存儲區的指針,該資料存儲區搜羅關于 CLI/ODBC 經管的資料源(資料庫)鄰接的資訊。
  • 語句句柄: 指向指向資料存儲區域的指針,該資料存儲區搜羅單個 SQL 語句有關的特定資訊。
  • 描寫符句柄: 指向一個資料存儲區域的指針,該資料存儲區搜羅一個中繼資料調集,這些中繼資料描寫被綁定到 SQL 語句中的參數标記的使用遞次變量,或者被綁定到盤考後果資料集中列的使用遞次變量。

每個 CLI/ODBC 使用遞次必須從分派一個環境句柄初步。平日每個使用遞次隻分派一個環境句柄,而且在分派任何其他句柄之前,誰人情況句柄必須已經存在。全部其他句柄都是在環境句柄使用的上下文環境中經管的。環境句柄可以議決挪用

SQLAllocHandle()

函數并指定

SQL_HANDLE_ENV

選項來分派。用于分派環境句柄的源代碼如下所示:

SQLHANDLE  EnvHandle = 0;
...
SQLAllocHandle(SQL_HANDLE_ENV, SQL_NULL_HANDLE, &EnvHandle);
              

在 CLI/ODBC 使用遞次中,到資料源的鄰接是議決鄰接句柄完成的。是以,在建樹就職何資料源的鄰接之前,必須存在一個鄰接句柄。可以議決挪用

SQLAllocHandle()

SQL_HANDLE_DBC

選項和一個無效的環境句柄來分派鄰接句柄。用于分派鄰接句柄的源代碼如下所示:

SQLHANDLE  ConHandle = 0;
...
if (EnvHandle != 0)
    SQLAllocHandle(SQL_HANDLE_DBC, EnvHandle, &ConHandle);
              

CLI/ODBC 使用遞次的真正骨幹是語句句柄。語句句柄用于:

  • 将使用遞次變量綁定到 SQL 語句中使用的參數标記。
  • 籌辦和送出 SQL 語句到恰當的資料源,以便執行。
  • 取得關于 SQL 語句産生的後果資料集的中繼資料。
  • 将使用遞次變量綁定到後果資料集中的列。
  • 從後果資料集中檢索(讀取)資料。
  • 當 SQL 未能執行時,取得診斷資訊。

CLI/ODBC 使用遞次中編寫的每條 SQL 語句都必須有它自己的語句句柄。每個語句句柄隻能與一個鄰接句柄相聯絡關系。可是,一個鄰接句柄可以與任意數目的語句句柄相聯絡關系。語句句柄可以議決挪用

SQLAllocHandle()

SQL_HANDLE_STMT

選項和一個無效的鄰接句柄來分派。是以,用于分派語句句柄的源代碼如下所示:

SQLHANDLE  StmtHandle = 0;
...
if (ConHandle != 0)
    SQLAllocHandle(SQL_HANDLE_STMT, ConHandle, &StmtHandle);    
              

每當分派一個語句句柄時,就會主動分派與語句句柄相聯絡關系的 4 個描寫符句柄。分派後,這些描寫符句柄蒙受與呼應的語句句柄相聯絡關系,直到它被銷毀(當時,描寫符句柄也随之被銷毀)。大年夜少數 CLI/ODBC 操縱都可以使用這些隐式界說的描寫符句柄來執行。可是,也可以議決挪用

SQLAllocHandle()

SQL_HANDLE_DESC

選項和無效的鄰接句柄來顯式地分派描寫符句柄。

DB2 9 使用斥地(733 考試)認證指南,第 5 局部: CLI/ODBC 程式設計(3)
DB2 9 使用斥地(733 考試)認證指南,第 5 局部: CLI/ODBC 程式設計(3)
DB2 9 使用斥地(733 考試)認證指南,第 5 局部: CLI/ODBC 程式設計(3)
DB2 9 使用斥地(733 考試)認證指南,第 5 局部: CLI/ODBC 程式設計(3)

聲明使用遞次 CLI/ODBC 版本

CLI 和 ODBC 使用特定于産物的驅動遞次來與資料源(資料庫)通信,大年夜少數驅動遞次都搜羅一組靜态參數,議決改削這些參數,可以變動驅動遞次的舉動,以滿足使用遞次的需求。這些參數被成為屬性,每個環境句柄、鄰接句柄和語句句柄都有其自己的一組屬性。(前面有一個小節描寫用于擷取和變動與環境句柄、鄰接句柄或語句句柄相聯絡關系的屬性。)環境屬性的一個例子是

SQL_ATTR_ODBC_VERSION

屬性,在分派環境句柄之後,分派任何呼應的鄰接句柄之前,必須為該屬性授予

SQL_OV_ODBC3

SQL_OV_ODBC2

值。這照顧 DB2 CLI 和 ODBC Driver Manager,使用遞次打算依從 CLI/ODBC 3.x 尺度或 CLI/ODBC 2.0(或更早版本)尺度。用于照顧 DB2 CLI 或 ODBC Driver Manager 使用遞次打算依從 CLI/ODBC 3.x(或更高版本)尺度的代碼如下所示:

...
SQLSetEnvAttr(EnvHandle, SQL_ATTR_ODBC_VERSION, (SQLPOINTER) SQL_OV_ODBC3,
    SQL_IS_UINTEGER);
              

讓 DB2 CLI 和 ODBC Driver Manager 曉得使用遞次依從何種尺度很次要,由于 CLI/ODBC 函數前往的良多前往碼(或者被稱為 SQLSTATE,SQLSTATEs 中會細緻談到)的值會因版本的分譬喻而分譬喻。其它,DB2 CLI 和 ODBC 的較高版本答應在某些函數參數中使用通配符,而較早版本則不該許。

DB2 9 使用斥地(733 考試)認證指南,第 5 局部: CLI/ODBC 程式設計(3)
DB2 9 使用斥地(733 考試)認證指南,第 5 局部: CLI/ODBC 程式設計(3)
DB2 9 使用斥地(733 考試)認證指南,第 5 局部: CLI/ODBC 程式設計(3)
DB2 9 使用斥地(733 考試)認證指南,第 5 局部: CLI/ODBC 程式設計(3)

建樹資料源(資料庫)鄰接

要對資料庫執行任何典範的操縱,必須起創始建到資料庫的鄰接。對付 CLI/ODBC 使用遞次,有 3 個函數可用于建樹資料源(資料庫)鄰接:

  • SQLConnect()

  • SQLDriverConnect()

  • SQLBrowseConnect()

使用遞次可以使用這 3 個函數的任意組合鄰接到任意數目的資料源,可是某些資料源或者會限定所支撐的活動鄰接的數目。(使用遞次可以議決挪用

SQLGetInfo()

SQL_MAX_DRIVER_CONNECTIONS

資訊典範來創造一個資料源支撐若幹很多多少活動鄰接。

SQLConnect()

函數目前是最簡樸的 CLI/ODBC 鄰接函數。當使用

SQLConnect()

函數時,它假定建樹鄰接所需的專注資訊就是一個資料源稱号,或者還有一個使用者 ID(受權 ID)和暗碼。(其他須要的資訊存儲在

db2cli.ini

檔案的

[COMMON]

局部、

ODBC.INI

[ODBC]

局部或體系系統資料庫中的 ODBC 子鍵中。)該函數希奇很是适用于隻須要使用者 ID 和密碼來鄰接資料源的使用遞次,以及須要供應其自己的鄰接界面或根底無需使用者界面的使用遞次。

SQLDriverConnect()

函數則答應使用遞次使用一個鄰接字元串将鄰接資訊發送到一個資料源驅動遞次(而不是将該資訊存儲在

db2cli.ini

檔案、

ODBC.INI

檔案或體系系統資料庫中,然後答應驅動遞次來檢索)。鄰接字元串是一系列的鍵/值對,之間以分号離隔,此中搜羅建樹到資料源鄰接時所需的資訊。表 1 列出了一些較常用的鍵/值對。

表 1. 和 SQLDriverConnect() 一路使用的鍵/值對 鍵/值 用處

DRIVER=DriverName

指定建樹到資料庫的鄰接所需使用的 CLI/ODBC 驅動遞次的稱号

DBALIAS=DatabaseAlias

指定要與之建樹鄰接的資料庫的别号

DSN=DataSourceName

指定要與之建樹鄰接的資料源的稱号(與

SQLDataSources()

函數前往的值分譬喻)

UID=UserID

指定嘗試建樹鄰接的使用者的使用者 ID(受權 ID)

PWD=Password

指定所指定使用者 ID(受權 ID)對應的暗碼。如果所指定的 ID 不須要暗碼,則應該使用一個空的暗碼字元串(

PWD=;

NEWPWD=NewPassword

指定為所指定使用者 ID(受權 ID)分派的新暗碼。如果使用了

NEWPWD

可是沒有供應新暗碼(

NEWPWD=;

),則 DB2 CLI 驅動遞次提示使用者供應一個新暗碼

是以,若要使用

SQLDriverConnect()

函數建樹到一個已編目的、名為 PAYROLL 的、使用受權 ID

db2admin

和暗碼

ibmdb2

的資料庫的鄰接,可以使用如下代碼:

...
char ConnectStr[512];
...
sprintf(ConString, "driver={IBM DB2 ODBC DRIVER};dbalias=payroll;
    uid=db2admin;pwd=ibmdb2");
SQLDriverConnect(ConHandle, NULL, (SQLCHAR *) ConnectStr, SQL_NTS, 
    NULL, 0, NULL, SQL_DRIVER_NOPROMPT);
...
	      

您或者細緻到,有一個名為

SQL_NTS

的特殊代碼被作為

SQLDriverConnect()

函數的一個參數值。蒙受字元串值作為參數的 CLI/ODBC 函數平日要求同時供應字元串的長度。可以使用

SQL_NTS

值替換理想長度值,表達呼應的字元串是以 null 制止的。

當被挪用時,

SQLDriverConnect()

函數使用指定的資料源稱号分解鄰接字元串,并嘗試從體系中擷取附加的資訊,以建樹鄰接。然後,該函數使用這些資訊登入到恰當的就事器上,并嘗試鄰接到指定的資料源。使用

SQLDriverConnect()

函數的使用遞次還可以讓驅動遞次提示使用者供應所需的鄰接資訊。比方,當用一個空鄰接字元串挪用

SQLDriverConnect()

函數時,DB2 CLI 表現一個對話框,提示使用者:

  1. 從 DB2 CLI 看法的資料源清單中選擇一個資料源。
  2. 供應一個使用者 ID 和呼應的暗碼。
  3. 指定鄰接情勢是獨有的還是共享的。

能否表現該對話框由轉達給

SQLDriverConnect()

函數的一個參數值節制:如果挪用該函數時指定了

SQL_DRIVER_PROMPT

SQL_DRIVER_COMPLETE

SQL_DRIVER_COMPLETE_REQUIRED

選項,那麼,如果供應的鄰接字元串沒有搜羅充足的資訊來建樹資料源鄰接,則表現該對話框。但如果指定了

SQL_DRIVER_NOPROMPT

選項,可是沒有供應充足的資訊,那麼就會前往錯誤。

SQLDriverConnect()

函數一樣,

SQLBrowseConnect()

函數使用一個鄰接字元串将鄰接資訊發送給驅動遞次。

SQLDriverConnect()

函數在編譯時須要一個無效的鄰接字元串,而

SQLBrowseConnect()

函數可用于在使用遞次運轉機會關一個鄰接。這點差别使使用遞次可以使用它自己的對話框提示使用者供應鄰接資訊,進而保管對其外觀的節制。

DB2 9 使用斥地(733 考試)認證指南,第 5 局部: CLI/ODBC 程式設計(3)
DB2 9 使用斥地(733 考試)認證指南,第 5 局部: CLI/ODBC 程式設計(3)
DB2 9 使用斥地(733 考試)認證指南,第 5 局部: CLI/ODBC 程式設計(3)
DB2 9 使用斥地(733 考試)認證指南,第 5 局部: CLI/ODBC 程式設計(3)

CLI/ODBC 使用遞次執行完恰當的初始化之後,焦點就轉移到事件處理下去。在此期間,議決分譬喻的 CLI/ODBC 函數挪用,将盤考和運用資料的 SQL 語句轉達到恰當的資料源(在這裡平日是 DB2 資料庫)進行處理。在事件處理期間,CLI/ODBC 使用遞次順次執行以下五個步調:

  1. 分派一個或多個語句句柄。
  2. 籌辦和執行一個或多個語句。
  3. 檢索和處理産生的後果。
  4. 議決送出或復原制止從此事件。
  5. 釋放分派的全部語句句柄。

圖 2 表現了事件處理期間執行的根底步調,并給出了常用于執行每個步調的 CLI/ODBC 函數挪用:

圖 2. 在 CLI/ODBC 使用遞次中處理事件
DB2 9 使用斥地(733 考試)認證指南,第 5 局部: CLI/ODBC 程式設計(3)
DB2 9 使用斥地(733 考試)認證指南,第 5 局部: CLI/ODBC 程式設計(3)
DB2 9 使用斥地(733 考試)認證指南,第 5 局部: CLI/ODBC 程式設計(3)
DB2 9 使用斥地(733 考試)認證指南,第 5 局部: CLI/ODBC 程式設計(3)
DB2 9 使用斥地(733 考試)認證指南,第 5 局部: CLI/ODBC 程式設計(3)

分派語句句柄

正如前面提到的,語句句柄援用一個資料對象,該對象搜羅單個 SQL 語句的有關資訊。這些資訊搜羅:

  • SQL 語句的文本
  • 關于與語句相聯絡關系的遊标的細緻資訊
  • 全部 SQL 語句參數标記變量的綁定
  • 全部後果資料集列變量的綁定
  • 語句執行的前往碼
  • 情況資訊

SQL 語句句柄是議決挪用

SQLAllocHandle()

SQL_HANDLE_STMT

選項和一個無效的鄰接句柄來分派的。在 CLI/ODBC 使用遞次執行任何 SQL 語句之前,必須至少分派一個語句句柄。

DB2 9 使用斥地(733 考試)認證指南,第 5 局部: CLI/ODBC 程式設計(3)
DB2 9 使用斥地(733 考試)認證指南,第 5 局部: CLI/ODBC 程式設計(3)
DB2 9 使用斥地(733 考試)認證指南,第 5 局部: CLI/ODBC 程式設計(3)
DB2 9 使用斥地(733 考試)認證指南,第 5 局部: CLI/ODBC 程式設計(3)

籌辦和執行 SQL 語句

分派好語句句柄後,就可以将一個 SQL 語句賦給它,處理 SQL 語句的體式格局有兩種:

  • 籌辦和執行 :這種體式格局将 SQL 語句的籌辦與執行分隔隔離雲集,平日用于須要重複執行語句的情況。如果使用遞次須要預知存在于執行 SQL 語句所産生的後果資料集中列的有關資訊,也使用該體式格局。這種體式格局使用 CLI/ODBC 函數

    SQLPrepare()

    SQLExecute()

    來處理 SQL 語句。
  • 當即執行 :該體式格局将 SQL 語句的籌辦和執行歸并為一個步調,平日用于語句隻執行一次的情況。如果使用遞次不須要關于 SQL 語句執行時所産生的後果資料集的附加資訊,那麼也可以使用該體式格局。這種體式格局使用 CLI/ODBC 函數

    SQLExecDirect()

這兩種體式格局都答應使用參數标記替換被處理的 SQL 語句中的常量和表達式。參數标記用問号(

?

)默示,用來訓示當執行 SQL 語句時将在 SQL 語句中的何處替換一個或多個使用遞次變量的從此值。當一個使用遞次變量與 SQL 語句中一個參數标記聯絡關系時,就稱該變量被“綁定”到該參數标記。這種綁定是議決挪用

SQLBindParameter()

函數完成的,使用遞次變量被綁定到參數标記之後,參數标記與該變量的聯絡關系就不斷無效,直到它被重載或者呼應的語句句柄被釋放。固然在 SQL 語句籌辦妥之後可以随時進行綁定,可是隻要到 SQL 語句執行的時間,才幹真正從綁定變量中檢索資料。

清單 1 顯現了在一個用 C 說話編寫的 CLI/ODBC 使用遞次中,如何将使用遞次變量綁定到簡樸的

SELECT

SQL 語句中的參數标記。它還顯現了在語句執行之前,将值以何種體式格局供應給綁定參數。

清單 1. 綁定參數标記
...
// Define A SELECT SQL Statement That Uses A Parameter Marker
strcpy((char *) SQLStmt, "SELECT empno, lastname FROM ");
strcat((char *) SQLStmt, "employee WHERE JOB = ?");
// Prepare The SQL Statement
RetCode = SQLPrepare(StmtHandle, SQLStmt, SQL_NTS);
// Bind The Parameter Marker Used In The SQL Statement To
// An Application Variable
RetCode = SQLBindParameter(StmtHandle, 1,
              SQL_PARAM_INPUT, SQL_C_CHAR, SQL_CHAR,
              sizeof(JobType), 0, JobType,
              sizeof(JobType), NULL);
// Populate The "Bound" Application Variable
strcpy((char *) JobType, "DESIGNER");
// Execute The SQL Statement
RetCode = SQLExecute(StmtHandle);
...
	      
DB2 9 使用斥地(733 考試)認證指南,第 5 局部: CLI/ODBC 程式設計(3)
DB2 9 使用斥地(733 考試)認證指南,第 5 局部: CLI/ODBC 程式設計(3)
DB2 9 使用斥地(733 考試)認證指南,第 5 局部: CLI/ODBC 程式設計(3)
DB2 9 使用斥地(733 考試)認證指南,第 5 局部: CLI/ODBC 程式設計(3)

檢索和處理後果

在籌辦并執行了 SQL 語句之後,須要檢索和處理該語句所産生的後果。如果 SQL 語句是

SELECT

VALUES

以外的語句,那麼在該語句執行之後,專注須要做的是檢查 CLI/ODBC 函數前往碼,以确認該語句能否按預期執行。可是,如果執行的 SQL 語句是一個盤考,那麼或者還須要進行呼應的處理來從産生的後果資料集中檢索資料。

當盤考前往多個行時,這些行被存儲在與執行的 SQL 語句相聯絡關系的鄰接句柄和語句句柄所援用的資料存儲區中。是以,或者須要執行以下步調來從産生的後果資料集中檢索資料:

  1. 确定産生的後果資料集的機關(即列的數目、列的資料典範、資料長度)。這可以議決執行

    SQLNumResultCols()

    SQLDescribeCol()

    SQLColAttributes()

    函數來完成。
  2. 使用

    SQLBindCol()

    函數将使用遞次變量綁定到後果資料集中的列上(可選)。
  3. 重複地從産生的後果資料集讀取下一行,并将之複制到綁定的使用遞次變量中。這平日是議決在一個循環中重複地挪用

    SQLFetch()

    函數來完成的。(每當讀取一個新行時,步調 2 中未綁定到使用遞次變量綁定的列值可以議決挪用

    SQLGetData()

    函數取得。)

在第一步中,起首分析所籌辦或執行的 SQL 語句,以确定産生的後果資料集的機關。如果 SQL 語句被寫死到使用遞次中,那麼不須要這一步,由于産生的後果資料集的機關是已知的。可是,如果 SQL 語句是在使用遞次運轉時生成的,那麼就必須盤考該語句産生的後果資料集,以取得該資訊。

曉得後果資料集的機關之後,可以将一個或多個使用遞次變量綁定到後果資料集中特定的列上(就像将使用遞次變量綁定到 SQL 語句參數标記一樣)。在這種情況下,使用遞次變量被用作輸出參數,而不是輸出參數,當挪用

SQLFetch()

函數時,就會檢索出資料并直接寫入這些變量中。可是,由于可以使用

SQLGetData()

函數從後果資料集中檢索資料,是以使用遞次變量/列綁定是可選的。

在第三步中,議決重複挪用

SQLFetch()

函數(平日在循環中),檢索存儲在後果資料集中的資料,直到資料被檢索完。如果已經将使用遞次變量綁定到後果資料集中的列上,那麼每當挪用

SQLFetch()

時,這些變量的值就會主動更新。另一方面,如果沒有執行列綁定,那麼可以使用

SQLGetData()

函數将資料從特定列中複制到恰當的使用遞次變量中。

SQLGetData()

函數還可用于在多個小局部中檢索大年夜型可變長度的列資料值(當使用綁定使用遞次變量時不能多麼做)。後果資料集中存儲的全部資料都可以使用這兩種體式格局的任意組合來檢索。

清單 2 顯現了在用 C 說話編寫的 CLI/ODBC 使用遞次中,如何将一個使用遞次變量綁定到後果資料集中的列上。它還顯現了平日如何議決重複地挪用

SQLFetch()

檢索後果資料集中的資料。

清單 2. 綁定列
...
// Bind The Columns In The Result Data Set Returned
// To Application Variables
SQLBindCol(StmtHandle, 1, SQL_C_CHAR, (SQLPOINTER) 
    EmpNo, sizeof(EmpNo), NULL);
SQLBindCol(StmtHandle, 2, SQL_C_CHAR, (SQLPOINTER) 
    LastName, sizeof(LastName), NULL);
// While There Are Records In The Result Data Set
// Produced, Retrieve And Display Them
while (RetCode != SQL_NO_DATA)
{
    RetCode = SQLFetch(StmtHandle);
    if (RetCode != SQL_NO_DATA)
        printf("%-8s %s\n", EmpNo, LastName);
}
...
	      
DB2 9 使用斥地(733 考試)認證指南,第 5 局部: CLI/ODBC 程式設計(3)
DB2 9 使用斥地(733 考試)認證指南,第 5 局部: CLI/ODBC 程式設計(3)
DB2 9 使用斥地(733 考試)認證指南,第 5 局部: CLI/ODBC 程式設計(3)
DB2 9 使用斥地(733 考試)認證指南,第 5 局部: CLI/ODBC 程式設計(3)

經處事件

您或者還記得,事件(也稱任務單元)是組分解一個單元的一個或多個 SQL 操縱的序列,它們平日位于一個使用遞次程序中。個給定的事件可以搜羅從一個單一操縱到成百乃至上千個任意數目的 SQL 操縱,次要取決于何為您的營業邏輯中以是為的單步。事件很次要,由于一個事件的初步和制止可以确定命據庫中的資料分譬喻性點。在一個事件中,要麼将事件中執行的全部操縱的後果長久地使用到資料庫中(送出),要麼回改全部操縱的後果(復原),并使資料庫前往到啟動事件之前所處的情況。

從事件處理的角度來看,可以将 CLI/ODBC 使用遞次設定為以兩種情勢中的一種來運轉:主動送出或手動送出。當使用主動送出情勢時,每個 SQL 語句都被算作一個齊備的事件,在 SQL 語句成功執行之後,每個事件都主動送出。對付除

SELECT

SQL 語句以外的語句,在語句執行之後就當即産生發火送出操縱。對付

SELECT

語句,當用于處理後果資料集的遊标封閉後,就當即産生發火送出操縱。(記住,CLI/ODBC 須要時會主動聲明并掀開一個遊标。)主動送出情勢是默許的送出情勢,對付簡樸的 CLI/ODBC 使用遞次平日就充足了。可是,對付一些大年夜型使用遞次,尤其是執行更新操縱的那些使用遞次,在建樹一個資料源鄰接之後,應應當即切換為手動送出情勢。用于切換得手動送出情勢的函數挪用如下所示:

SQLSetConnectAttr(ConHandle, SQL_ATTR_AUTOCOMMIT, SQL_AUTOCOMMIT_OFF, SQL_IS_UINTEGER);
              

當使用手動送出情勢時,會在使用遞次初次接見一個資料源時隐式地初步事件,在挪用

SQLEndTran()

函數時顯式地竣事事件。這個 CLI/ODBC 函數用于復原或送出從此事件所做的全部變動。是以,從資料源第一次被接見初步,到挪用

SQLEndTran()

函數為止,這段時間内在資料源上執行的全部操縱都被算作一個事件。

DB2 9 使用斥地(733 考試)認證指南,第 5 局部: CLI/ODBC 程式設計(3)
DB2 9 使用斥地(733 考試)認證指南,第 5 局部: CLI/ODBC 程式設計(3)
DB2 9 使用斥地(733 考試)認證指南,第 5 局部: CLI/ODBC 程式設計(3)
DB2 9 使用斥地(733 考試)認證指南,第 5 局部: CLI/ODBC 程式設計(3)

釋放語句句柄

當 SQL 語句的後果被處理終了,而且不再須要事件處理初步時分派的 SQL 語句資料存儲區時,應該釋放為該資料存儲保管的記憶體。要釋放與特定語句句柄相聯絡關系的資料存儲區,可以挪用

SQLFreeHandle()

SQL_HANDLE_STMT

選項和恰當的語句句柄(比方

SQLFreeHandle(SQL_HANDLE_STMT, StmtHandle)

)來完成。當被挪用時,CLI/ODBC 函數執行以下任務:

  • 消除對全部之前綁定的參數使用遞次變量的綁定
  • 消除對全部之前綁定的列使用遞次變量的綁定
  • 封閉已掀開的遊标,并甩失蹤其後果
  • 銷毀指定的句柄,并釋放全部關系本錢

如果一個語句句柄沒有被釋放,那麼它還可以用于處理其他 SQL 語句。

DB2 9 使用斥地(733 考試)認證指南,第 5 局部: CLI/ODBC 程式設計(3)
DB2 9 使用斥地(733 考試)認證指南,第 5 局部: CLI/ODBC 程式設計(3)
DB2 9 使用斥地(733 考試)認證指南,第 5 局部: CLI/ODBC 程式設計(3)
DB2 9 使用斥地(733 考試)認證指南,第 5 局部: CLI/ODBC 程式設計(3)

制止資料源鄰接

在 CLI/ODBC 使用遞次制止,而且節制被前往到操縱體系之前,應該制止已建樹的全部資料源鄰接,并釋放初始化期間分派的全部本錢。(平日,這些本錢由一個環境資料存儲區和一個或多個鄰接資料存儲區構成。)

#include <stdio.h>
#include <string.h>
#include <sqlcli1.h>
int main()
{
    // Declare The Local Memory Variables
    SQLHANDLE  EnvHandle = 0;
    SQLHANDLE  ConHandle = 0;
    SQLHANDLE  StmtHandle = 0;
    SQLRETURN  RetCode = SQL_SUCCESS;
    SQLCHAR    SQLStmt[255];
    SQLCHAR    JobType[10];
    SQLCHAR    EmpNo[10];
    SQLCHAR    LastName[25];
    /*-----------------------------------------------------*/
    /* INITIALIZATION                                      */
    /*-----------------------------------------------------*/
    // Allocate An Environment Handle
    SQLAllocHandle(SQL_HANDLE_ENV, SQL_NULL_HANDLE,
        &EnvHandle);
    // Set The ODBC 使用遞次 Version To 3.x
    if (EnvHandle != 0)
        SQLSetEnvAttr(EnvHandle, SQL_ATTR_ODBC_VERSION, 
            (SQLPOINTER) SQL_OV_ODBC3, SQL_IS_UINTEGER);
    // Allocate A Connection Handle
    if (EnvHandle != 0)
        SQLAllocHandle(SQL_HANDLE_DBC, EnvHandle,
            &ConHandle);
    // Connect To The Appropriate Data Source 
    if (ConHandle != 0)
        RetCode = SQLConnect(ConHandle, (SQLCHAR *) "SAMPLE",
                      SQL_NTS, (SQLCHAR *) "db2admin",
                      SQL_NTS, (SQLCHAR *) "ibmdb2",
                      SQL_NTS);
    /*-----------------------------------------------------*/
    /* TRANSACTION PROCESSING                              */
    /*-----------------------------------------------------*/
    // Allocate An SQL Statement Handle
    if (ConHandle != 0 && RetCode == SQL_SUCCESS)
        SQLAllocHandle(SQL_HANDLE_STMT, ConHandle,
           &StmtHandle);
    // Define A SELECT SQL Statement That Uses A Parameter
    // Marker
    strcpy((char *) SQLStmt, "SELECT empno, lastname FROM ");
    strcat((char *) SQLStmt, "employee WHERE job = ?");
    // Prepare The SQL Statement
    RetCode = SQLPrepare(StmtHandle, SQLStmt, SQL_NTS);
    // Bind The Parameter Marker Used In The SQL Statement To
// An Application Variable
    RetCode = SQLBindParameter(StmtHandle, 1,
                  SQL_PARAM_INPUT, SQL_C_CHAR, SQL_CHAR,
                  sizeof(JobType), 0, JobType,
                  sizeof(JobType), NULL);
  // Populate The "Bound" Application Variable
    strcpy((char *) JobType, "DESIGNER");
    // Execute The SQL Statement
    RetCode = SQLExecute(StmtHandle);
    // If The SQL Statement Executed Successfully, Retrieve
    // The Results
    if (RetCode == SQL_SUCCESS)
    {
       // Bind The Columns In The Result Data Set Returned
        // To Application Variables
        SQLBindCol(StmtHandle, 1, SQL_C_CHAR, (SQLPOINTER) 
            EmpNo, sizeof(EmpNo), NULL);
        SQLBindCol(StmtHandle, 2, SQL_C_CHAR, (SQLPOINTER) 
            LastName, sizeof(LastName), NULL);
        // While There Are Records In The Result Data Set
        // Produced, Retrieve And Display Them
        while (RetCode != SQL_NO_DATA)
        {
            RetCode = SQLFetch(StmtHandle);
            if (RetCode != SQL_NO_DATA)
                printf("%-8s %s\n", EmpNo, LastName);
        }
    }
    // Commit The Transaction
    RetCode = SQLEndTran(SQL_HANDLE_DBC, ConHandle, SQL_COMMIT);
    // Free The SQL Statement Handle
    if (StmtHandle != 0)
        SQLFreeHandle(SQL_HANDLE_STMT, StmtHandle);
    /*-----------------------------------------------------*/
    /* TERMINATION                                         */
    /*-----------------------------------------------------*/
    // Terminate The Data Source Connection
    if (ConHandle != 0)
        RetCode = SQLDisconnect(ConHandle);
    // Free The Connection Handle
    if (ConHandle != 0)
        SQLFreeHandle(SQL_HANDLE_DBC, ConHandle);
    // Free The Environment Handle
    if (EnvHandle != 0)
        SQLFreeHandle(SQL_HANDLE_ENV, EnvHandle);
    // Return Control To The Operating System
    return(0);
}   
              

版權聲明:

原創作品,答應轉載,轉載時請務必以超連結情勢标明文章 原始出處 、作者資訊和本聲明。不然将窮究執法責任。