dyma82
asked on
ODBC / SQL with C++
Hi. I have a MSSQLServer 7.0 database full of data. I need to access this data and play with it using a C++ program. I already have the whole thing. The only thing I am missing is the part where the program actualy opens a connection to the DataBase and execute SQL statements.
How can I interact with a MSSQLServer database using C++. (NO......!!!! MFC !!!!!.....).
Thaks a lot for your time.
How can I interact with a MSSQLServer database using C++. (NO......!!!! MFC !!!!!.....).
Thaks a lot for your time.
I'd encourage you to rethink your opposition to MFC in this case. The encapsulation of ADODB via CDaoDatabase is a MAJOR time saver.
Perhaps, however, you're a "real-man" kind of programmer who doesn't want to use any of those wimpy class libraries. In that case, you have the full power of the Windows DAO librries at your disposal.
Perhaps, however, you're a "real-man" kind of programmer who doesn't want to use any of those wimpy class libraries. In that case, you have the full power of the Windows DAO librries at your disposal.
this is a simple example ive knocked up for you, create a simple access or sql server database and create
a system dsn for it in control panel. the open function uses global varaibles etc so you will probably
want to chage this.
/* for db stuff */
#include <windows.h>
#include <sql.h>
#include <sqlext.h>
#include <stdio.h>
HENV henv;
HDBC hdbc;
int dbopen=0;
/* opens a connection using global variables , bad i know */
#define PM_DSN "your_system_dsn"
#define PM_DSN_USER "your_db_username_if_any"
#define PM_DSN_PW "your_password_if_any"
int DBopen(void)
{
int res=0;
RETCODE retcode;
/*allocate the environment handle*/
if(SQLAllocEnv(&henv)==SQL _SUCCESS)
{
/*allocate the connection handle*/
if(SQLAllocConnect(henv, &hdbc)==SQL_SUCCESS)
{
/* Set login timeout to 5 seconds. */
SQLSetConnectOption(hdbc, SQL_LOGIN_TIMEOUT, 5);
SQLSetConnectOption(hdbc, SQL_CURSOR_TYPE, SQL_CURSOR_STATIC);
/* Connect to data source */
retcode = SQLConnect(hdbc, PM_DSN, SQL_NTS, PM_DSN_USER, SQL_NTS, PM_DSN_PW, SQL_NTS);
if (retcode == SQL_SUCCESS || retcode == SQL_SUCCESS_WITH_INFO)
{
res=1;
}
}
else
{
SQLFreeConnect(hdbc);
}
}
else
{
SQLFreeEnv(henv);
}
dbopen=res;
return res;
}
void DBclose(void)
{
if(dbopen)
{
SQLDisconnect(hdbc);
SQLFreeConnect(hdbc);
SQLFreeEnv(henv);
if(DATABASE_NAME)
{
free(DATABASE_NAME);
}
}
dbopen=0;
}
int DBexecute(char *sql,HSTMT *hstmt)
{
int res=0;
RETCODE retcode;
if(SQLAllocStmt(hdbc, hstmt)== SQL_SUCCESS)
{
retcode=SQLPrepare(*hstmt, sql,strlen (sql));
if(retcode==SQL_SUCCESS)
{
retcode=SQLExecute(*hstmt) ;
if(retcode==SQL_SUCCESS)
{
res=1;
}
}
}
return res;
}
void DBcloseCursor(HSTMT hstmt)
{
SQLFreeStmt(hstmt, SQL_DROP);
}
void main()
{
char sql[255];
HSTMT fstmt;
long lens;
RETCODE retcode;
char name[100];
DBopen();
sprintf(sql,"SELECT name FROM users");
if(DBexecute(sql,&fstmt))
{
SQLBindCol(fstmt,1,SQL_C_C HAR, name,sizeof(name),&lens);
retcode = SQLFetch(fstmt);
while(retcode == SQL_SUCCESS || retcode == SQL_SUCCESS_WITH_INFO)
{
printf("%s\n",name);
retcode = SQLFetch(fstmt);
}
DBcloseCursor(fstmt);
}
DBclose();
}
a system dsn for it in control panel. the open function uses global varaibles etc so you will probably
want to chage this.
/* for db stuff */
#include <windows.h>
#include <sql.h>
#include <sqlext.h>
#include <stdio.h>
HENV henv;
HDBC hdbc;
int dbopen=0;
/* opens a connection using global variables , bad i know */
#define PM_DSN "your_system_dsn"
#define PM_DSN_USER "your_db_username_if_any"
#define PM_DSN_PW "your_password_if_any"
int DBopen(void)
{
int res=0;
RETCODE retcode;
/*allocate the environment handle*/
if(SQLAllocEnv(&henv)==SQL
{
/*allocate the connection handle*/
if(SQLAllocConnect(henv, &hdbc)==SQL_SUCCESS)
{
/* Set login timeout to 5 seconds. */
SQLSetConnectOption(hdbc, SQL_LOGIN_TIMEOUT, 5);
SQLSetConnectOption(hdbc, SQL_CURSOR_TYPE, SQL_CURSOR_STATIC);
/* Connect to data source */
retcode = SQLConnect(hdbc, PM_DSN, SQL_NTS, PM_DSN_USER, SQL_NTS, PM_DSN_PW, SQL_NTS);
if (retcode == SQL_SUCCESS || retcode == SQL_SUCCESS_WITH_INFO)
{
res=1;
}
}
else
{
SQLFreeConnect(hdbc);
}
}
else
{
SQLFreeEnv(henv);
}
dbopen=res;
return res;
}
void DBclose(void)
{
if(dbopen)
{
SQLDisconnect(hdbc);
SQLFreeConnect(hdbc);
SQLFreeEnv(henv);
if(DATABASE_NAME)
{
free(DATABASE_NAME);
}
}
dbopen=0;
}
int DBexecute(char *sql,HSTMT *hstmt)
{
int res=0;
RETCODE retcode;
if(SQLAllocStmt(hdbc, hstmt)== SQL_SUCCESS)
{
retcode=SQLPrepare(*hstmt,
if(retcode==SQL_SUCCESS)
{
retcode=SQLExecute(*hstmt)
if(retcode==SQL_SUCCESS)
{
res=1;
}
}
}
return res;
}
void DBcloseCursor(HSTMT hstmt)
{
SQLFreeStmt(hstmt, SQL_DROP);
}
void main()
{
char sql[255];
HSTMT fstmt;
long lens;
RETCODE retcode;
char name[100];
DBopen();
sprintf(sql,"SELECT name FROM users");
if(DBexecute(sql,&fstmt))
{
SQLBindCol(fstmt,1,SQL_C_C
retcode = SQLFetch(fstmt);
while(retcode == SQL_SUCCESS || retcode == SQL_SUCCESS_WITH_INFO)
{
printf("%s\n",name);
retcode = SQLFetch(fstmt);
}
DBcloseCursor(fstmt);
}
DBclose();
}
ASKER
Thanks a lot guys for your prompt response. I liked your tone JHance because I hate MFC. I love Win32 APIs. Thanks a lot Makerp. I will try that tonight. I am a Java programmer, but I have always been in love with C (ANSI), which I use to code for fun. Now I am trying seriously to reach the same level I enjoy in Java in C++. I know that's the most powerful language of them all.
Thanks again.
I'll get back to you guys tomorrow.
Thanks again.
I'll get back to you guys tomorrow.
all ODBC calls begin with SQL, so if you type in SQL in the VC++ help index you will get a list of all data structs and functions etc. rememeber all of the MFC classes are built on the ODBC API anyway, look at the MFC code and see
ASKER
Hi guys. Following is the code I am using to try to connect and query a MSSQLServer database. Of course, it is a modification of "makerp's" code. However, for some reason the function SQLExecDirect(), is not working properly. It returns a SQL_ERROR code. I have been trying to find what's wrong, but without luck.
Can you guys look at this function to see what's wrong with it?????
Thanks a lot
Here is my code :
#include <iostream.h>
#include <windows.h>
#include <sql.h>
#include <sqlext.h>
#include <string.h>
//#include <stdio.h>
//HENV henv;//environment handle
//SQLHENV henv1;
SQLHANDLE henv1;
//HDBC hdbc;//Connection Handle
//SQLHDBC hdbc1;
SQLHANDLE hdbc1;
//Statement Handler
SQLHANDLE StmtHandler;
int dbopen=0;
/* opens a connection using global variables , bad i know */
#define PM_DSN "BPSA"
#define PM_DSN_USER "sa"
#define PM_DSN_PW ""
int DBopen(void)
{
int res=0;
SQLRETURN retcode;
int ODBCVersion = SQL_OV_ODBC3;
int LoginTimeOUT = 5;
int ODBCCursor = SQL_CUR_USE_IF_NEEDED;
char *SQLQuery = {"SELECT USER_ID,PASSWORD FROM accountInfo"};
char UserID[50];
char AccountNumber[50];
char Password[50];
char Name[50];
char ClientName[50];
long c;
/*allocate the environment handle*/
//if(SQLAllocEnv(&henv)==S QL_SUCCESS )
if(SQLAllocHandle(SQL_HAND LE_ENV,SQL _NULL_HAND LE, &henv1)==SQL_SUCCESS)
{
/*allocate the connection handle*/
SQLSetEnvAttr(henv1,SQL_AT TR_ODBC_VE RSION,(voi d*)SQL_OV_ ODBC3,0);
retcode = SQLAllocHandle(SQL_HANDLE_ DBC, henv1, &hdbc1);
if(retcode==SQL_SUCCESS)
{
/* Set login timeout to 5 seconds. */
SQLSetConnectAttr(hdbc1, SQL_ATTR_LOGIN_TIMEOUT, &LoginTimeOUT, 0);
SQLSetConnectAttr(hdbc1, SQL_ATTR_ODBC_CURSORS, &ODBCCursor, 0);
/* Connect to data source */
retcode = SQLConnect(hdbc1, (unsigned char *)PM_DSN,5,(unsigned char *)PM_DSN_USER,3,(unsigned char *)PM_DSN_PW,0);
if (retcode == SQL_SUCCESS || retcode == SQL_SUCCESS_WITH_INFO)
{
//Getting a Statement Handler, so to submit SQL queries.
if(SQLAllocHandle(SQL_HAND LE_STMT,hd bc1, &StmtHandler)==SQL_SUCCESS )
{
res=1;
cout<<"All Handlers allocated correctly ...!!!"<<endl;
retcode = SQLExecDirect(StmtHandler, (unsigned char *)SQLQuery,strlen(SQLQuery ));
if(retcode==SQL_SUCCESS)
{
cout<<"Statement Executed successfully"<<endl<<endl;
cout<<"User_ID AccountNumber Password Name ClientName"<<endl;
while(true)
{
retcode = SQLFetch(StmtHandler);
if((retcode==SQL_ERROR) || (retcode==SQL_SUCCESS_WITH _INFO))
{
cout<<"Error fetching the data...!!"<<endl;
}
else
{
if(retcode==SQL_SUCCESS)
{
cout<<"Data fetched successfully....!!!!"<<end l;
SQLGetData(StmtHandler,1,S QL_C_CHAR, UserID,50, &c);
SQLGetData(StmtHandler,2,S QL_C_CHAR, AccountNum ber,50,&c) ;
SQLGetData(StmtHandler,3,S QL_C_CHAR, Password,5 0,&c);
SQLGetData(StmtHandler,4,S QL_C_CHAR, Name,50,&c );
cout<<UserID<<"----"<<Acco untNumber< <"----"<<P assword<<" ----"<<Nam e<<"----"< <ClientNam e<<endl;
}
else
{
cout<<"probable end of result-set"<<endl;
SQLFreeHandle(SQL_HANDLE_S TMT,StmtHa ndler);
SQLFreeHandle(SQL_HANDLE_D BC,hdbc1);
SQLFreeHandle(SQL_HANDLE_E NV,henv1);
}
}
}
}
else
{
cout<<"Error executing the statement...!!! --- error = "<<retcode<<endl;
cout<<"Query length = "<<strlen(SQLQuery)<<endl;
if(retcode==SQL_SUCCESS_WI TH_INFO)
cout<<"Code = SQL_SUCCESS_WITH_INFO"<<en dl;
else if(retcode==SQL_NEED_DATA)
cout<<"Code = SQL_NEED_DATA"<<endl;
else if(retcode==SQL_STILL_EXEC UTING)
cout<<"Code = SQL_STILL_EXECUTING"<<endl ;
else if(retcode==SQL_ERROR)
cout<<"Code = SQL_ERROR"<<endl;
else if(retcode==SQL_NO_DATA)
cout<<"Code = SQL_NO_DATA"<<endl;
else if(retcode==SQL_INVALID_HA NDLE)
cout<<"Code = SQL_INVALID_HANDLE"<<endl;
SQLFreeHandle(SQL_HANDLE_S TMT,StmtHa ndler);
}
}
}
}
else
{
cout<<"Error allocating connection handler --- error = "<<retcode<<endl;
SQLFreeHandle(SQL_HANDLE_D BC,hdbc1);
}
}
else
{
cout<<"Error allocating environment handler --- error = "<<retcode<<endl;
SQLFreeHandle(SQL_HANDLE_E NV,henv1);
}
dbopen=res;
return res;
}
int main()
{
cout<<"Starting....."<<end l;
DBopen();
cout<<"end of function ...!!!"<<endl;
return 0;
}
Can you guys look at this function to see what's wrong with it?????
Thanks a lot
Here is my code :
#include <iostream.h>
#include <windows.h>
#include <sql.h>
#include <sqlext.h>
#include <string.h>
//#include <stdio.h>
//HENV henv;//environment handle
//SQLHENV henv1;
SQLHANDLE henv1;
//HDBC hdbc;//Connection Handle
//SQLHDBC hdbc1;
SQLHANDLE hdbc1;
//Statement Handler
SQLHANDLE StmtHandler;
int dbopen=0;
/* opens a connection using global variables , bad i know */
#define PM_DSN "BPSA"
#define PM_DSN_USER "sa"
#define PM_DSN_PW ""
int DBopen(void)
{
int res=0;
SQLRETURN retcode;
int ODBCVersion = SQL_OV_ODBC3;
int LoginTimeOUT = 5;
int ODBCCursor = SQL_CUR_USE_IF_NEEDED;
char *SQLQuery = {"SELECT USER_ID,PASSWORD FROM accountInfo"};
char UserID[50];
char AccountNumber[50];
char Password[50];
char Name[50];
char ClientName[50];
long c;
/*allocate the environment handle*/
//if(SQLAllocEnv(&henv)==S
if(SQLAllocHandle(SQL_HAND
{
/*allocate the connection handle*/
SQLSetEnvAttr(henv1,SQL_AT
retcode = SQLAllocHandle(SQL_HANDLE_
if(retcode==SQL_SUCCESS)
{
/* Set login timeout to 5 seconds. */
SQLSetConnectAttr(hdbc1, SQL_ATTR_LOGIN_TIMEOUT, &LoginTimeOUT, 0);
SQLSetConnectAttr(hdbc1, SQL_ATTR_ODBC_CURSORS, &ODBCCursor, 0);
/* Connect to data source */
retcode = SQLConnect(hdbc1, (unsigned char *)PM_DSN,5,(unsigned char *)PM_DSN_USER,3,(unsigned char *)PM_DSN_PW,0);
if (retcode == SQL_SUCCESS || retcode == SQL_SUCCESS_WITH_INFO)
{
//Getting a Statement Handler, so to submit SQL queries.
if(SQLAllocHandle(SQL_HAND
{
res=1;
cout<<"All Handlers allocated correctly ...!!!"<<endl;
retcode = SQLExecDirect(StmtHandler,
if(retcode==SQL_SUCCESS)
{
cout<<"Statement Executed successfully"<<endl<<endl;
cout<<"User_ID AccountNumber Password Name ClientName"<<endl;
while(true)
{
retcode = SQLFetch(StmtHandler);
if((retcode==SQL_ERROR) || (retcode==SQL_SUCCESS_WITH
{
cout<<"Error fetching the data...!!"<<endl;
}
else
{
if(retcode==SQL_SUCCESS)
{
cout<<"Data fetched successfully....!!!!"<<end
SQLGetData(StmtHandler,1,S
SQLGetData(StmtHandler,2,S
SQLGetData(StmtHandler,3,S
SQLGetData(StmtHandler,4,S
cout<<UserID<<"----"<<Acco
}
else
{
cout<<"probable end of result-set"<<endl;
SQLFreeHandle(SQL_HANDLE_S
SQLFreeHandle(SQL_HANDLE_D
SQLFreeHandle(SQL_HANDLE_E
}
}
}
}
else
{
cout<<"Error executing the statement...!!! --- error = "<<retcode<<endl;
cout<<"Query length = "<<strlen(SQLQuery)<<endl;
if(retcode==SQL_SUCCESS_WI
cout<<"Code = SQL_SUCCESS_WITH_INFO"<<en
else if(retcode==SQL_NEED_DATA)
cout<<"Code = SQL_NEED_DATA"<<endl;
else if(retcode==SQL_STILL_EXEC
cout<<"Code = SQL_STILL_EXECUTING"<<endl
else if(retcode==SQL_ERROR)
cout<<"Code = SQL_ERROR"<<endl;
else if(retcode==SQL_NO_DATA)
cout<<"Code = SQL_NO_DATA"<<endl;
else if(retcode==SQL_INVALID_HA
cout<<"Code = SQL_INVALID_HANDLE"<<endl;
SQLFreeHandle(SQL_HANDLE_S
}
}
}
}
else
{
cout<<"Error allocating connection handler --- error = "<<retcode<<endl;
SQLFreeHandle(SQL_HANDLE_D
}
}
else
{
cout<<"Error allocating environment handler --- error = "<<retcode<<endl;
SQLFreeHandle(SQL_HANDLE_E
}
dbopen=res;
return res;
}
int main()
{
cout<<"Starting....."<<end
DBopen();
cout<<"end of function ...!!!"<<endl;
return 0;
}
sorry, i have not used this api for a while so i dont know why it dont work.
BTW
when you pass the stlen of the sql string to the prepare or exec function add 1 for the null, on MS db's this is not required and will make no difference but it will crash if using an oracle driver
BTW
when you pass the stlen of the sql string to the prepare or exec function add 1 for the null, on MS db's this is not required and will make no difference but it will crash if using an oracle driver
why do you not use my prewritten functions
ASKER
Makerp : Documentation say those functions are deprecated. Is that ok, if I use them anyway. Will it work on Windows 2000 and MSSQLServer 7.0????
Thanks a lot for your time.
Thanks a lot for your time.
ASKER CERTIFIED SOLUTION
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
The ODBC driver manager will also translate calls from deprecated (ODBC 1.0 & 2.0) into ODBC 3.0 where the driver demands it.
Its slower but it make life easy.
Andy.
Its slower but it make life easy.
Andy.
http://as400bks.rochester.ibm.com/pubs/html/as400/v4r4/ic2924/info/db2/rzadpmst55.htm