| 网站首页 | JAVA文章 | AppServers | Web开发 | 应用开发 | 资源下载 | 论坛
    想学好编程,学好外语很重要  [enadd  2006年12月25日]        
设为首页 加入收藏 联系站长
您现在的位置: 编程笔记网 >> 应用开发 >> vc >> 数据库 >> 文章正文
用Visual C++开发数据库应用程序(三)        【字体:
用Visual C++开发数据库应用程序(三)
作者:-    文章来源:-    点击数:    更新时间:2006-4-20

2.24 SQL操作

构造和执行SQL语句

构造SQL语句

可以通过三种方式构造SQL语句:在程序开发阶段确定、在运行时确定或由用户输入SQL语句。

在程序开发时确定的SQL语句,具有易于实现、且可在程序编码时进行测试的优势。

在程序运行时确定SQL语句提供了极大灵活性,但给程序高度带来了困难,且需更多的处理时间。由用户输入的SQL语句,极大的增强了程序的功能,但是,程序必须提供友好的人机界面,且对用户输入的语句执行一定程序的语法检查,能够报告用户错误。

执行SQL语句

应用程序的绝大部分数据库访问工作都是通过执行SQL语句完成的,在执行SQL语句之前,必须要先分配一个语句句柄,然后设置相应语句的语句属性,再执行SQL语句。当一个语句句柄使用完成后,调用函数SQLFreeHandle()释放该句柄。


SQLExecute()

SQLExecute用于执行一个准备好的语然,当语句中有参数时,用当前绑定的参数变量的值。

函数格式:

SQLRETURN SQLExecute(SQLHSTMT StatementHandle);

参数:

StatementHandle 标识执行SQL语句的句柄,可以用SQLAllocHandle()来获得。

返回值:

SQL_SUCCESS, SQL_SUCCESS_W99vH_INFO, SQL_NEED_DATA, SQL_STILL_EXECUTING, SQL_ERROR, SQL_NO_DATA, or SQL_INVALID_HANDLE

成功返回SQL_SUCCESS,如果返回值为SQL_ERROR或SQL_SUCCESS_W99vH_INFO,可以用函数SQLGetDiagRec获取相应SQLSTATE的值。 


SQLExecDiret()

SQLExecDirect直接执行SQL语句,对于只执行一次的操作来说,该函数是速度最快的方法。

函数格式:

SQLRETURN SQLExecDirect(SQLHSTMT StatementHandle,SQLCHAR *StatementText,SQLINTEGER TextLength);

参数:

StatementHandle 语句句柄

StatementText 要执行的SQL语然

StatementText SQL语句的长度。

返回值:

SQL_SUCCESS, SQL_SUCCESS_W99vH_INFO, SQL_NEED_DATA, SQL_STILL_EXECUTING, SQL_ERROR, SQL_NO_DATA, or SQL_INVALID_HANDLE

成功返回SQL_SUCCESS,如果返回值为SQL_ERROR或SQL_SUCCESS_W99vH_INFO,可以用函数SQLGetDiagRec获取相应SQLSTATE的值。 


SQLPripare()

对于需多次执行的SQL语句来说,除了使用SQLExecDirect函数之外,我们也可以在执行SQL语句之前,先准备SQL语句的执行。对于使用参数的语句,这可大提高程序执行速度。

函数格式:

SQLRETURN SQLPrepare(SQLHSTMT StatementHandle,SQLCHAR* StatementText,SQLINTEGER TextLength);

参数:

StatementHandle 语句句柄

StatementText 要执行的SQL语然

StatementText SQL语句的长度。

返回值:

SQL_SUCCESS, SQL_SUCCESS_W99vH_INFO, SQL_NEED_DATA, SQL_STILL_EXECUTING, SQL_ERROR, SQL_NO_DATA, or SQL_INVALID_HANDLE

成功返回SQL_SUCCESS,如果返回值为SQL_ERROR或SQL_SUCCESS_W99vH_INFO,可以用函数SQLGetDiagRec获取相应SQLSTATE的值。 

使用参数

使用参数可以使一条SQL语句多次执行,得到不同结果

SQLBindParameter

函数SQLBindParameter负责为参数定义变量,实现参数值的传递。

函数格式如下:

SQLRETURNSQLBindParameter(SQLHSTMT StatementHandle,SQLUSMALLINT ParameterNumber,SQLSMALLINT InputOutputType,SQLSMALLINT ValueType,SQLSMALLINT ParameterType,SQLUINTEGER ColumnSize,SQLSMALLINT DecimalDigits,SQLPOINTER ParameterValuePtr,SQLINTEGER BufferLength,SQLINTEGER *StrLen_or_IndPtr);

参数:

StatementHandle 语句句柄

ParameterNumber 绑定的参数在SQL语句中的序号,在SQL中,所有参数从左到右顺序编号,从1开始。SQL语句执行之前,应该为每个参数调用函数SQLBindParameter绑定到某个程序变量。

InputOutputType 参数类型,可为SQL_PARA_INPUT, SQL_PARAM_INPUT_OUTPUT, SQL_PARAM_OUTPUT。

ParameterType 参数数据类型

ColumnSIze 参数大小

DecimalDigits 参数精度

ParameterValutePtr 指向程序中存放参数值的缓冲区的指针

BufferLength 程序中存放参数值的缓冲区的字节数

StrLen_or_IndPtr 指向存放参数ParameterValuePtr的缓冲区指针

返回值:

SQL_SUCCESS, SQL_SUCCESS_W99vH_INFO, SQL_ERROR, or SQL_INVALID_HANDLE

成功返回SQL_SUCCESS,如果返回值为SQL_ERROR或SQL_SUCCESS_W99vH_INFO,可以用函数SQLGetDiagRec获取相应SQLSTATE的值。

执行时传递参数

对于某些文本文档或位图文件,要占用大量的存储空间。因此,在数据源传递这些数据时,可以分开传递。有两个函数可完成这个工作。

函数格式:

SQLRETURN SQLPutData(SQLHSTMT StatementHandle,

SQLPOINTER DataPtr,SQLINTEGER StrLen_or_Ind);

参数:

StatementHandle 参数句柄

DataPtr 指向包含实际数据的缓冲区指针。

StrLen_or_Lnd 缓冲区长度

返回值:

SQL_SUCCESS, SQL_SUCCESS_W99vH_INFO, SQL_ERROR, or SQL_INVALID_HANDLE

成功返回SQL_SUCCESS,如果返回值为SQL_ERROR或SQL_SUCCESS_W99vH_INFO,可以用函数SQLGetDiagRec获取相应SQLSTATE的值。

函数格式:

SQLRETURNSQLParamData(SQLHSTMT StatementHandle,SQLPOINTER *ValuePtrPtr);

参数:

StatementHandle 参数句柄

ValuePtrPtr 指向缓冲区地址的指针

返回值:

SQL_SUCCESS, SQL_SUCCESS_W99vH_INFO, SQL_ERROR, or SQL_INVALID_HANDLE

成功返回SQL_SUCCESS,如果返回值为SQL_ERROR或SQL_SUCCESS_W99vH_INFO,可以用函数SQLGetDiagRec获取相应SQLSTATE的值。  

下面的代码展示如何使用这两个函数

#define MAX_DATA_LEN 1024

SQLINTEGER cbPartID = 0, cbPhotoParam, cbData;

SQLUINTEGER sPartID; szPhotoFile;

SQLPOINTER pToken, InitValue;

SQLCHAR Data[MAX_DATA_LEN];

SQLRETURN retcode;

SQLHSTMT hstmt;

retcode = SQLPrepare(hstmt, "INSERT INTO PICTURES (PARTID, PICTURE) VALUES

(?, ?)", SQL_NTS);

if (retcode == SQL_SUCCESS || retcode == SQL_SUCCESS_W99vH_INFO) {

/* Bind the parameters. For parameter 2, pass */

/* the parameter number in ParameterValuePtr instead of a buffer */

/* address. */ SQLBindParameter(hstmt, 1, SQL_PARAM_INPUT, SQL_C_ULONG,

SQL_INTEGER, 0, 0, &sPartID, 0, &cbPartID);

SQLBindParameter(hstmt, 2, SQL_PARAM_INPUT,

SQL_C_BINARY, SQL_LONGVARBINARY,

0, 0, (SQLPOINTER) 2, 0, &cbPhotoParam);

/* Set values so data for parameter 2 will be */

/* passed at execution. Note that the length parameter in */

/* the macro SQL_LEN_DATA_AT_EXEC is 0. This assumes that */

/* the driver returns "N" for the SQL_NEED_LONG_DATA_LEN */

/* information type in SQLGetInfo. */

cbPhotoParam = SQL_LEN_DATA_AT_EXEC(0);

sPartID = GetNextID(); /* Get next available employee ID */

/* number. */ retcode = SQLExecute(hstmt);

/* For data-at-execution parameters, call SQLParamData to */

/* get the parameter number set by SQLBindParameter. */

/* Call InitUserData. Call GetUserData and SQLPutData */

/* repeatedly to get and put all data for the parameter. */

/* Call SQLParamData to finish processing this parameter */

while (retcode == SQL_NEED_DATA) {

retcode = SQLParamData(hstmt, &pToken);

if (retcode == SQL_NEED_DATA) {

InitUserData((SQLSMALLINT)pToken, InitValue);

while (GetUserData(InitValue, (SQLSMALLINT)pToken, Data,

&cbData))

SQLPutData(hstmt, Data, cbData); } }}

VOID InitUserData(sParam, InitValue)SQLPOINTER InitValue;{

SQLCHAR szPhotoFile[MAX_FILE_NAME_LEN];

/* Prompt user for bitmap file containing employee */

/* photo. OpenPhotoFile opens the file and returns the */ /* file handle. */

PromptPhotoFileName(szPhotoFile);

OpenPhotoFile(szPhotoFile, (FILE *)InitValue); break; }

BOOL GetUserData(InitValue, sParam, Data, cbData)SQLPOINTER InitValue;

SQLCHAR *Data;SQLINTEGER *cbData;BOOL Done;{

/* GetNextPhotoData returns the next piece of photo */

/* data and the number of bytes of data returned */

/* (up to MAX_DATA_LEN). */ Done = GetNextPhotoData((FILE *)InitValue, Data,

MAX_DATA_LEN, &cbData); if (Done) {

ClosePhotoFile((FILE *)InitValue);

return (TRUE); }

return (FALSE); }

记录的添加、删除和更新

应用程序对数据源的数据更新可以通过三种方式实现:使用相应的SQL语句在数据源上执行;调用函数SQLSetPos实现记录集的定义更新;调用函数SQLBulkOperations实现数据的更新。

直接在数据源上执行SQL语句的方式,可以适用于任何的ODBC数据源,但是,对于后两种更新方式,有的数据源并不支持,应用程序可以调用函数SQLGetInfo确定数据源是否支持这两种方式。


定位更新和删除

要使用定位更新和删除功能,要按如下顺序:

1)取回记录集:

2)定位到要进行更新或删除操作的行

3)执行更新或删除操作 

参考如下的代码:

#define ROWS 20#define STATUS_LEN 6

SQLCHAR szStatus[ROWS][STATUS_LEN], szReply[3];

SQLINTEGER cbStatus[ROWS], cbOrderID;

SQLUSMALLINT rgfRowStatus[ROWS];

SQLUINTEGER sOrderID, crow = ROWS, irow;

SQLHSTMT hstmtS, hstmtU;

SQLSetStmtAttr(hstmtS, SQL_ATTR_CONCURRENCY, (SQLPOINTER) SQL_CONCUR_ROWVER, 0);

SQLSetStmtAttr(hstmtS, SQL_ATTR_CURSOR_TYPE, (SQLPOINTER) SQL_CURSOR_KEYSET_DRIVEN, 0);

SQLSetStmtAttr(hstmtS, SQL_ATTR_ROW_ARRAY_SIZE, (SQLPOINTER) ROWS, 0);

SQLSetStmtAttr(hstmtS, SQL_ATTR_ROW_STATUS_PTR, (SQLPOINTER) rgfRowStatus, 0);

SQLSetCursorName(hstmtS, "C1", SQL_NTS);

SQLExecDirect(hstmtS, "SELECT ORDERID, STATUS FROM ORDERS ", SQL_NTS);

SQLBindCol(hstmtS, 1, SQL_C_ULONG, &sOrderID, 0, &cbOrderID);

SQLBindCol(hstmtS, 2, SQL_C_CHAR, szStatus, STATUS_LEN, &cbStatus);

while ((retcode == SQLFetchScroll(hstmtS, SQL_FETCH_NEXT, 0)) != SQL_ERROR) {

if (retcode == SQL_NO_DATA_FOUND) break;

for (irow = 0; irow < crow; irow++) {

if (rgfRowStatus[irow] != SQL_ROW_DELETED)

printf("%2d %5d %*s\n", irow+1, sOrderID, NAME_LEN-1, szStatus[irow]);

} while (TRUE) { printf("\nRow number to update?");

gets(szReply); irow = atoi(szReply);

if (irow > 0 && irow <= crow) { printf("\nNew status?");

gets(szStatus[irow-1]);

SQLSetPos(hstmtS, irow, SQL_POS99vION, SQL_LOCK_NO_CHANGE);

SQLPrepare(hstmtU,

"UPDATE ORDERS SET STATUS=? WHERE CURRENT OF C1", SQL_NTS);

SQLBindParameter(hstmtU, 1, SQL_PARAM_INPUT,

SQL_C_CHAR, SQL_CHAR,

STATUS_LEN, 0, szStatus[irow], 0, NULL);

SQLExecute(hstmtU); } else if (irow == 0) { break; }

}

}



用SQLBulkOperations()更新数据

函数SQLBulkOperations的操作是基于当前行集的,在调用函数SQLBulkOperations之前,必须先调用函数SQLFetch或SQLFetchScroll获取行集,然后,再执行修改或删除操作。 

函数格式:

SQLRETURN SQLBulkOperations(SQLHSTMT StatementHandle,

SQLUSMALLINT Operation); 


参数

[1] [2] [3] [4] [5] [6] [7] 下一页  

文章录入:enadd    责任编辑:enadd 
  • 上一篇文章:

  • 下一篇文章:
  • 发表评论】【加入收藏】【告诉好友】【打印此文】【关闭窗口
    最新热点 最新推荐 相关文章
  • Visual C++ ADO数据库编程入…

  • isual C++ ADO数据库编程入门…

  • 用Visual C++开发数据库应用…

  • 在Visual C++中用ADO进行数据…

  • Visual C++中的ODBC编程实例

  • 一个简单的学生成绩管理软件…

  • 用Visual C++开发数据库应用…

  • VC用ADO访问数据库全攻略

  • 用Visual C++开发数据库应用…

  • 用Visual C++开发数据库应用…

  •   网友评论:(只显示最新10条。评论内容只代表网友观点,与本站立场无关!)
    | 设为首页 | 加入收藏 | 联系站长 | 友情链接 | 版权申明 | 管理登录 |