用ODBC API进行编程时,如何使用SQL语句的SELECT语句
编号:QA003969
建立日期: 2001年3月8日 最后修改日期:2002年12月8日
所属类别:
佚名:
操作系统:win98
编程工具:VC++ 6.0
问题:我是一名学VC++ 6.0的高中生,在用ODBC API进行编程时遇到了几天来我一直没能解决的困难,请给予解答是盼!!!
问题是这样的,我想把SQL语句加到我的程序中去,例如在编一个查询函数时,中心语句用:
select * from list1(表) where name1(字段名)=某某, 这样就可以比用AddNew()好得多,面且又能提高准确性,还有在进行"事务"处理时,也是非常方便的,一句话就是我想把SQL语句用到我的某个函数中在某方面也许它比普通的编程要烦,但很多方面是非常方便的!!!
我的程序的在体过程是这样的,第一:打开数据源(即连接数据源);
第二:向DBMS提交SQL语句(即SQLExecDirect()等;
第三:获取数据(比例SQLBindCol(),SQLFetch(),SQLGetData()等);
大体过程就是这样的,我的思想是它(SQL语句)只是对数据源操作而不是对记录集作用,所以它相当于在VC++中的向导过程(即RFX过程由自己来完成sqlbindcol()),打开数据源后,是否还要打开记录集啊?
我的想法是不是又不对啊?
下面是我的程序:
void testdlg::OnSqlrowButton1()
{
// TODO: Add your control notification handler code here
SQLRETURN retcode;
SQLINTEGER coum_courseeind,mmm;
SQLCHAR coum_courseeidset[23];
SQLCHAR godcome[50];
CDatabase db;
retcode=db.Open(_T("学生资料"));
if(retcode==SQL_SUCCESS||retcode==SQL_SUCCESS_WITH_INFO)
MessageBox("source is opened now"); file://运行结果得此步
else
MessageBox("failure to open source");
COleVariant varname;
CRecordset rs;
rs.m_pDatabase=&db;
// rs.Open();
SQLCHAR statement[90]="select * from 课程 WHERE 课号='MATH333'";
SQLBindCol(rs.m_hstmt,1,SQL_C_CHAR,coum_courseeidset,sizeof(coum_courseeidset),
&coum_courseeind);
SQLExecDirect(rs.m_hstmt,statement,SQL_NTS);
if(SQLFetch(rs.m_hstmt)!=SQL_NO_DATA)
MessageBox("ok,you can fetch your data"); // 运行结果得此步
else
MessageBox("fail to get data");
SQLGetData(rs.m_hstmt,1,SQL_C_CHAR,godcome,sizeof(godcome),&mmm);
char thuf[12];
sprintf(thuf,"the %s file",godcome);
AfxMessageBox(thuf); // 结果为"the 烫烫...... y file
}
邦定的数据源字段返回的值总是不对!!
还有SQLBindCol()和SQLGetdata()这两个函数能否对每一个参数都给我详细指点一下,特别是后面的三个参数。
几天啦,我都没能从这里争脱出来,好困好累,真有点失去信心了,这不是以前的我,真诚盼望你们能给我解答,好吗?若不能请给我个回音,好吗? 还有啊,若可能,请给我一个在一个函数中实现利用SQL的完整例子,谢谢!!
回答:
通过程序实现对数据库数据的查询时可以使用ODBC API,也可以使用MFC中提供的类CDatabase和CRecordset等。类CDatabase和CRecordset是对ODBC API的封装。而从你提的问题,可以看出你的思路有些混乱了,一会用类库,一会又用ODBC API。
通过类CDatabase和CRecordset实现对数据库的查询,很简单。其中CDatabase是建立数据库连接,而任何查询语句,都是需要获得查询的结果,所以是需要打开结果集的。
(1)使用类库进行查询的过程,大体如下:
CString strConnect;
strConnect.Format("ODBC;DSN=%s;UID=%s;PWD=%s",m_strCombDSN,m_strUID,m_strPswd);
CDatabase db;
if(!db.Open(NULL,FALSE,FALSE,strConnect,TRUE))
return FALSE;
CString strSql="select * from 课 程 WHERE 课 号 ='MATH333'";
CRecordset rs(db);
rs.Open(CRecordset::snapshot, strSQL,
CRecordset::readOnly | CRecordset::useMultiRowFetch);
while (!rs.IsEOF())
{
//根据情况调用GetODBCFieldCount()、GetRowsFetched、CRecordset::GetFieldValue()等,取出数据
}
(2)使用ODBC API获得查询结果的方法大体如下:
RETCODE loc_retcode;
HDBC loc_hdbc;
unsigned char* szDSN=(unsigned char *)DSN;
unsigned char* szUID=(unsigned char *)UID;
unsigned char* szAuthStr=(unsigned char *)PWD;
loc_retcode=SQLAllocConnect(GDAI_henv,&loc_hdbc); file://创建连接句柄
if (!(loc_retcode==SQL_SUCCESS || loc_retcode==SQL_SUCCESS_WITH_INFO))
return -1;
loc_retcode=SQLConnect(loc_hdbc,szDSN,SQL_NTS,szUID,SQL_NTS,szAuthStr,SQL_NTS);//建立与数据源的连接
if (!loc_retcode==SQL_SUCCESS)
{
GetErrorInfoFromODBC(loc_hdbc);
SQLFreeConnect(loc_hdbc);//连接失败
return -1;
}
SQLAllocStmt(loc_hdbc,&loc_hstmt);
SWORD pccol; file://存放结果集中返回的列数
char szColName[129];
short cbColName;
short sqlType;
UDWORD ColDef;
short Scale;
short Nullable;
loc_retcode=SQLExecDirect(loc_hstmt, (unsigned char*)pSQL, strlen(pSQL));
loc_retcode = SQLFetch(loc_hstmt);
while(loc_retcode ==SQL_SUCCESS||loc_retcode == SQL_SUCCESS_WITH_INFO)
{
//取每列数据 例如 SQLGetData(hstmt, icol, SQL_C_CHAR, v_data->data, 511, &pcbValue);
loc_retcode = SQLFetch(loc_hstmt);
}
关于这类数据库功能的原码在VC的例子程序中应该就可以获得。
Odin的意见:
对ODBC API我不太熟悉,但是下面这个网址中提供的类 SQLDirect是一个类似于CRecordset 的对ODBC的封装。里面有真正的动态绑定的内容。可能可以作为一个好例子。
http://www.codeguru.com/mfc_database/direct_sql_with_odbc.shtml
forallthenights问:
请问这条sql语句中
CString strSql="select * from 课 程 WHERE 课 号 ='MATH333'"
的math33如果要换成变量该怎么写?
如果要用m_strFilter,
是不是m_strFilter="课 号 =" + 变量;
如果我用m_pDatabase->ExecuteSQL(sql),这个sql该怎么写?
李海答:
如果s是一个字符串变量,可以这样写:
CString strSql="select * from 课 程 WHERE 课 号 ='" + s + "'";
此问题由autumn回答。
| |
|
|
| |
|
|