if ( (retcode != SQL_SUCCESS) && (retcode != SQL_SUCCESS_WITH_INFO) ) {
ProcessLogMessages(SQL_HANDLE_STMT, hstmt1,\ }
retcode = SQLBindParameter(hstmt1, 11,
SQL_PARAM_INPUT_OUTPUT, SQL_C_CHAR,SQL_VARCHAR, 20, 0, szIO, 20, &cb11); if ( (retcode != SQL_SUCCESS) && (retcode != SQL_SUCCESS_WITH_INFO) ) {
ProcessLogMessages(SQL_HANDLE_STMT, hstmt1,\ }
retcode = SQLBindParameter(hstmt1, 12,
SQL_PARAM_INPUT_OUTPUT, SQL_C_DOUBLE,SQL_FLOAT, 0, 0, &fIO, 0, &cb12); if ( (retcode != SQL_SUCCESS) && (retcode != SQL_SUCCESS_WITH_INFO) ) {
ProcessLogMessages(SQL_HANDLE_STMT, hstmt1,\ }
retcode = SQLBindParameter(hstmt1, 13,
SQL_PARAM_INPUT_OUTPUT, SQL_C_CHAR,SQL_DECIMAL, 25, 10, szIO2, 40, &cb13); if ( (retcode != SQL_SUCCESS) && (retcode != SQL_SUCCESS_WITH_INFO) ) {
ProcessLogMessages(SQL_HANDLE_STMT, hstmt1,\ }
// execute
retcode = SQLExecDirect (hstmt1,szSQL, SQL_NTS); if ( (retcode != SQL_SUCCESS) && (retcode != SQL_SUCCESS_WITH_INFO) ) {
ProcessLogMessages(SQL_HANDLE_STMT, hstmt1,\ } else
while ( ( retcode = SQLMoreResults(hstmt1) ) != SQL_NO_DATA ) ;
TRACE(%utput,szOutput2);
TRACE(\ SQLFreeHandle(SQL_HANDLE_STMT,hstmt1); }
首先讲一下如何提供NULL值,大家看看第5个参数的调用语句。 cb6= SQL_NULL_DATA;
retcode = SQLBindParameter(hstmt1, 6, SQL_PARAM_INPUT, SQL_C_LONG,SQL_INTEGER, 0, 0, NULL, 0, &cb6);
关键在与最后一个参数设置为SQL_NULL_DATA。而cb7 = SQL_NTS表示字符串以NULL字符结尾,你可以将 cb7赋值为 strlen( szInput ) 函数也可以正常执行。
你对比输入参数,输出参数和既输入又输出参数的调用方式,你会发现非常类似,区别主要在最后一个参数是否需要先赋值和执行完成后是否会返回数据。 输出参数:retcode = SQLBindParameter(hstmt1, 2, SQL_PARAM_OUTPUT, SQL_C_LONG,SQL_INTEGER, 0, 0, &iOutput, 0, &cb2);
输入参数:retcode = SQLBindParameter(hstmt1, 6, SQL_PARAM_INPUT, SQL_C_LONG,SQL_INTEGER, 0, 0, NULL, 0, &cb6);
输入输出参数:retcode = SQLBindParameter(hstmt1, 10, SQL_PARAM_INPUT_OUTPUT, SQL_C_LONG,SQL_INTEGER, 0, 0, &iIO, 0, &cb10);
2.5.5 SQL的准备与执行
在ODBC中除支持SQL语句的直接执行(利用SQLExecDirect)外还可以使用准备-执行的方式,在准备阶段ODBC会分析SQL语句并分配各种资源,在执行阶段才正式执行刚才准备好的SQL语句。在这中模式下会使用下面的两个API函数。 准备需要执行的SQL语句: SQLRETURN SQLPrepare(
SQLHSTMT StatementHandle, SQLCHAR * StatementText, SQLINTEGER TextLength); StatementHandle:STMT句柄。
StatementText:包含SQL语句的字符串。
TextLength:SQL语句的长度,或者使用SQL_NTS 表示SQL语句以NULL字符结尾。 执行经过准备的SQL语句:
SQLRETURN SQLExecute(SQLHSTMT StatementHandle);
在执行SQL语句时可以利用SQLPrepare 和SQLExecute 的组合来代替SQLExecDirect函数。
使用SQLExecute执行和SQLExecDirect 执行后的STMT句柄可以进行相同的操作,例如使用SQLFetch取得结果集。不过准备-执行模式一般用来执行各种大批量的数据修改,而不是用来执行查询语句。此外对于那些需要反复执行的SQL语句利用准备-执行模式会比反复执行SQLExecDirect 速度快。当执行数据修改时可以采用前面提到过的参数绑定,并且每执行一次重新后修改参数的值。
首先在数据库内添加下面的测试表:create table test_insert(testid int,testname varchar(20)) 。
下面的例子使用准备-执行的模式来插入数据,第一个SQL语句是删除语句,第二个语句是插入语句,利用参数绑定来修改每次插入的实际值。在每次执行后利用SQLRowCount 函数得到修改的数据行的数量。 void OnTestP7() {
SQLCHAR szInput[20];
SQLINTEGER iInput=0,iRowCount=0; SQLCHAR szSQL1[200]=\
test_insert\ SQLINTEGER cb1=0,cb2=SQL_NTS; //delete
retcode = SQLAllocHandle(SQL_HANDLE_STMT, hdbc1, &hstmt1);
retcode = SQLPrepare(hstmt1,szSQL1,SQL_NTS); if ( (retcode != SQL_SUCCESS) && (retcode != SQL_SUCCESS_WITH_INFO) ) {
ProcessLogMessages(SQL_HANDLE_STMT, hstmt1,\ }
retcode = SQLExecute(hstmt1);
if ( (retcode != SQL_SUCCESS) && (retcode != SQL_SUCCESS_WITH_INFO) ) {
ProcessLogMessages(SQL_HANDLE_STMT, hstmt1,\ }
SQLRowCount(hstmt1,&iRowCount);
printf(\ SQLFreeHandle(SQL_HANDLE_STMT,hstmt1); // insert
retcode = SQLAllocHandle(SQL_HANDLE_STMT, hdbc1, &hstmt1);
retcode = SQLPrepare(hstmt1,szSQL2,SQL_NTS); if ( (retcode != SQL_SUCCESS) && (retcode != SQL_SUCCESS_WITH_INFO) ) {
ProcessLogMessages(SQL_HANDLE_STMT, hstmt1,\ }
retcode = SQLBindParameter(hstmt1, 1, SQL_PARAM_INPUT, SQL_C_LONG,SQL_INTEGER, 0, 0, &iInput, 0, &cb1);
if ( (retcode != SQL_SUCCESS) && (retcode != SQL_SUCCESS_WITH_INFO) ) {
ProcessLogMessages(SQL_HANDLE_STMT, hstmt1,\