DB2 9 使用斥地(733 考试)认证指南,第 5 局部: CLI/ODBC 编程(3)

developerWorks








机关 CLI/ODBC 使用递次

CLI/ODBC 使用递次的构成局部

全部 CLI/ODBC 使用递次都要被机关来执行以下三个分譬喻的任务:

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

每个任务触及到的任务是议决挪用一个或多个 CLI/ODBC API 函数来完成的。用于完成这些任务的良多 CLI/ODBC 函数必须依照特定的递次来挪用,不然会产生发火错误。图 1 标出了用于执行初始化和制止任务的一些根底的 CLI/ODBC 函数:

图 1. CLI/ODBC 使用递次执行的根底任务
CLI/ODBC 任务

CLI/ODBC 使用递次还可以执行图 1 中列出的 3 个任务以外的任务,比方错误处理和动态处理。在前面的小节 诊断和错误处理 中,可以看到 CLI/ODBC 使用递次中如何处理错误。





回页首



分派本钱

在初始化期间,须要分派(和初始化)处理事件所需的本钱,并建树到事件处理任务须要使用的数据源的邻接。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 选项和无效的邻接句柄来显式地分派描写符句柄。





回页首



声明使用递次 CLI/ODBC 版本

CLI 和 ODBC 使用特定于产物的驱动递次来与数据源(数据库)通信,大年夜少数驱动递次都搜罗一组静态参数,议决改削这些参数,可以变动驱动递次的举动,以满足使用递次的需求。这些参数被成为属性,每个环境句柄、邻接句柄和语句句柄都有其自己的一组属性。(前面有一个小节描写用于获取和变动与环境句柄、邻接句柄或语句句柄相联络关系的属性。)环境属性的一个例子是 SQL_ATTR_ODBC_VERSION 属性,在分派环境句柄之后,分派任何呼应的邻接句柄之前,必须为该属性授予 SQL_OV_ODBC3SQL_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 的较高版本答应在某些函数参数中使用通配符,而较早版本则不该许。





回页首



建树数据源(数据库)邻接

要对数据库执行任何典范的操纵,必须起创始建到数据库的邻接。对付 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_PROMPTSQL_DRIVER_COMPLETESQL_DRIVER_COMPLETE_REQUIRED 选项,那么,如果供应的邻接字符串没有搜罗充足的信息来建树数据源邻接,则表现该对话框。但如果指定了 SQL_DRIVER_NOPROMPT 选项,可是没有供应充足的信息,那么就会前往错误。

SQLDriverConnect() 函数一样,SQLBrowseConnect() 函数使用一个邻接字符串将邻接信息发送给驱动递次。SQLDriverConnect() 函数在编译时须要一个无效的邻接字符串,而 SQLBrowseConnect() 函数可用于在使用递次运转机会关一个邻接。这点差别使使用递次可以使用它自己的对话框提示用户供应邻接信息,从而保管对其外观的节制。





回页首



事件处理

CLI/ODBC 使用递次执行完恰当的初始化之后,焦点就转移到事件处理下去。在此期间,议决分譬喻的 CLI/ODBC 函数挪用,将盘考和运用数据的 SQL 语句转达到恰当的数据源(在这里平日是 DB2 数据库)进行处理。在事件处理期间,CLI/ODBC 使用递次顺次执行以下五个步调:

  1. 分派一个或多个语句句柄。
  2. 筹办和执行一个或多个语句。
  3. 检索和处理产生的后果。
  4. 议决提交或回滚制止从此事件。
  5. 释放分派的全部语句句柄。


图 2 表现了事件处理期间执行的根底步调,并给出了常用于执行每个步调的 CLI/ODBC 函数挪用:

图 2. 在 CLI/ODBC 使用递次中处理事件
CLI/ODBC 事件处理





回页首



分派语句句柄

正如前面提到的,语句句柄援用一个数据对象,该对象搜罗单个 SQL 语句的有关信息。这些信息搜罗:

  • SQL 语句的文本
  • 关于与语句相联络关系的游标的细致信息
  • 全部 SQL 语句参数标记变量的绑定
  • 全部后果数据集列变量的绑定
  • 语句执行的前往码
  • 情况信息

SQL 语句句柄是议决挪用 SQLAllocHandle() 函数并指定 SQL_HANDLE_STMT 选项和一个无效的邻接句柄来分派的。在 CLI/ODBC 使用递次执行任何 SQL 语句之前,必须至少分派一个语句句柄。





回页首



筹办和执行 SQL 语句

分派好语句句柄后,就可以将一个 SQL 语句赋给它,处理 SQL 语句的体式格局有两种:

  • 筹办和执行:这种体式格局将 SQL 语句的筹办与执行分隔隔离云集,平日用于须要重复执行语句的情况。如果使用递次须要预知存在于执行 SQL 语句所产生的后果数据集中列的有关信息,也使用该体式格局。这种体式格局使用 CLI/ODBC 函数 SQLPrepare()SQLExecute() 来处理 SQL 语句。

  • 当即执行:该体式格局将 SQL 语句的筹办和执行归并为一个步调,平日用于语句只执行一次的情况。如果使用递次不须要关于 SQL 语句执行时所产生的后果数据集的附加信息,那么也可以使用该体式格局。这种体式格局使用 CLI/ODBC 函数 SQLExecDirect() 来处理 SQL 语句。

这两种体式格局都答应使用参数标记替换被处理的 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);
...
	







回页首



检索和处理后果

在筹办并执行了 SQL 语句之后,须要检索和处理该语句所产生的后果。如果 SQL 语句是 SELECTVALUES 以外的语句,那么在该语句执行之后,专注须要做的是检查 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);
}
...
	







回页首



经处事件

您或者还记得,事件(也称任务单元)是组分解一个单元的一个或多个 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() 函数为止,这段时间内在数据源上执行的全部操纵都被算作一个事件。





回页首



释放语句句柄

当 SQL 语句的后果被处理终了,而且不再须要事件处理初步时分派的 SQL 语句数据存储区时,应该释放为该数据存储保管的内存。要释放与特定语句句柄相联络关系的数据存储区,可以挪用 SQLFreeHandle() 函数并指定 SQL_HANDLE_STMT 选项和恰当的语句句柄(比方 SQLFreeHandle(SQL_HANDLE_STMT, StmtHandle))来完成。当被挪用时,CLI/ODBC 函数执行以下任务:

  • 消除对全部之前绑定的参数使用递次变量的绑定
  • 消除对全部之前绑定的列使用递次变量的绑定
  • 封闭已掀开的游标,并甩失踪其后果
  • 销毁指定的句柄,并释放全部关系本钱

如果一个语句句柄没有被释放,那么它还可以用于处理其他 SQL 语句。





回页首



制止数据源邻接

在 CLI/ODBC 使用递次制止,而且节制被前往到操纵体系之前,应该制止已建树的全部数据源邻接,并释放初始化期间分派的全部本钱。(平日,这些本钱由一个环境数据存储区和一个或多个邻接数据存储区构成。)

议决挪用 SQLDisconnect() 函数并指定恰当的邻接句柄,制止已有的数据库邻接。为了释放呼应的邻接数据存储区,用 SQL_HANDLE_DBC 选项挪用 SQLFreeHandle() 函数并指定恰当的邻接句柄。当之前分派的全部邻接数据存储区都被释放后,议决用 SQL_HANDLE_ENV 选项并指定恰当的环境句柄来挪用 SQLFreeHandle() 函数,释放与邻接数据存储区相联络关系的环境数据存储区。





回页首



综述

检查了构成全部 CLI/ODBC 使用递次的根底组件之后,现在就让我们来看一看如何邻接这些组件以产生与 DB2 数据库交互的 CLI/ODBC 使用递次。下面是用 C 说话编写的一个简朴的 CLI/ODBC 使用递次,该使用递次获取并打印职位为 DESIGNER 的全部雇员的雇员编号和姓氏:

清单 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);
}   
        





版权声明: 原创作品,答应转载,转载时请务必以超链接情势标明文章 原始出处 、作者信息和本声明。不然将穷究执法责任。

原文地址:https://www.cnblogs.com/zgqjymx/p/1972844.html