meetze
asked on
returning sql values
I am trying to find a way to return values in C++ from a sql expression that I send to the database. I can run queries like "DELETE FROM TABLE_NAME" without a problem. But I want return a value from a sql statement...example "SELECT COUNT(ID) FROM TABLE_NAME"...I would like the count to be stored in a variable in my program. Does any one have a way to do this??? Thanks.
ASKER
yes I would appreciate the code...would this class support dynamic queries?? For example...can I use the same class to run a number of different queiries that have a different number of return values???
ASKER CERTIFIED SOLUTION
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
ASKER
Appdev....these are all API calls??? It will work for returning one value..but what if the query returns multiple records??
This is the code. With a loop and another API call.
Sorry, I forgot the header files.
#include <sqlfront.h>
#include <sqldb.h>
PDBPROCESS *dbproc;
char *Acc="MyAccount";
char *Password="MyPassword";
char *Server="MyServer";
char *DBName="MyDB";
PLOGINREC loginrec;
RETCODE rc=SUCCEED;
if(dbinit() == (char *)NULL){
sprintf("Communication failure with [%s]",Server);
return -1;
}
loginrec = (PLOGINREC)dblogin();
DBSETLUSER ((PLOGINREC)loginrec, Acc);
DBSETLAPP ((PLOGINREC)loginrec, "meetze");
DBSETLPWD ((PLOGINREC)loginrec, Password);
if( (*dbproc = dbopen ((PLOGINREC)loginrec,Serve r)) == NULL)
return -1;
if ((rc=dbuse (*dbproc,DBName)) == FAIL) {
sprintf ("I can't open %s",DBNombre);
return -1;
}
You're connected and the database is open.
/////////////////
DBINT count,ID;
RETCODE rc=SUCCEED;
rc = dbcmd(dbproc,"SELECT COUNT(ID),ID FROM TABLE_NAME");
if ( (rc = dbsqlexec(dbproc)) != SUCCEED ) {
MessageBox("Error executing SELECT","meetze",MB_OK | MB_ICONEXCLAMATION);
return -1;
}
if ((rc = dbresults(dbproc)) == SUCCEED) {
rc=dbbind(dbproc, 1, INTBIND, (DBINT)0, (BYTE *)&count);
rc=dbbind(dbproc, 2, INTBIND, (DBINT)0, (BYTE *)&ID);
}
char Buffer[50];
while ( (rc=dbnextrow(dbproc)) != NO_MORE_ROWS ){
sprintf(Buffer,"There are %s of %s",count,ID);
MessageBox(Buffer,"meetze" ,MB_OK | MB_ICONEXCLAMATION);
}
Sorry, I forgot the header files.
#include <sqlfront.h>
#include <sqldb.h>
PDBPROCESS *dbproc;
char *Acc="MyAccount";
char *Password="MyPassword";
char *Server="MyServer";
char *DBName="MyDB";
PLOGINREC loginrec;
RETCODE rc=SUCCEED;
if(dbinit() == (char *)NULL){
sprintf("Communication failure with [%s]",Server);
return -1;
}
loginrec = (PLOGINREC)dblogin();
DBSETLUSER ((PLOGINREC)loginrec, Acc);
DBSETLAPP ((PLOGINREC)loginrec, "meetze");
DBSETLPWD ((PLOGINREC)loginrec, Password);
if( (*dbproc = dbopen ((PLOGINREC)loginrec,Serve
return -1;
if ((rc=dbuse (*dbproc,DBName)) == FAIL) {
sprintf ("I can't open %s",DBNombre);
return -1;
}
You're connected and the database is open.
/////////////////
DBINT count,ID;
RETCODE rc=SUCCEED;
rc = dbcmd(dbproc,"SELECT COUNT(ID),ID FROM TABLE_NAME");
if ( (rc = dbsqlexec(dbproc)) != SUCCEED ) {
MessageBox("Error executing SELECT","meetze",MB_OK | MB_ICONEXCLAMATION);
return -1;
}
if ((rc = dbresults(dbproc)) == SUCCEED) {
rc=dbbind(dbproc, 1, INTBIND, (DBINT)0, (BYTE *)&count);
rc=dbbind(dbproc, 2, INTBIND, (DBINT)0, (BYTE *)&ID);
}
char Buffer[50];
while ( (rc=dbnextrow(dbproc)) != NO_MORE_ROWS ){
sprintf(Buffer,"There are %s of %s",count,ID);
MessageBox(Buffer,"meetze"
}
You don't need to use the DB-Library or anything else. You can accomplish
same very easily with very few lines of code. Depending upon your query type
you can make the query return any value with or without using a class structure.
For e.g. If all you ever want from this kind of function is a count, it does not make
too much sense to create a class. You need to be more specific in your need
before you can create a class.
For the above mentioned query, I find this function to be the most convenient. It
is assumed here that the tablename you are querying is accessible from pointer
to recordset. If this is not the case, you need to somehow provide the complete
SQL query to the function before it executes countSet.Open ...
//It will return current record count for any open record set. Since this value is not //ODBC-layer dependant, it is generally lot more reliable
long GetRecordsetCount(CRecords et *pSet)
{
try
{
CRecordset countSet(pSet->m_pDatabase );
CString strQuery;
CString strTableName;
CDBVariant dbValue;
strTableName = pSet->GetDefaultSQL();
// No reserved words should already be in use
ASSERT(strTableName.Find(" SELECT") < 0);
ASSERT(strTableName.Find(" FROM") < 0);
ASSERT(strTableName.Find(" WHERE") < 0);
strQuery.Format("SELECT COUNT(*) CNT FROM %s",strTableName);
countSet.m_strFilter = pSet->m_strFilter;
countSet.Open(CRecordset:: forwardOnl y, strQuery);
countSet.GetFieldValue((sh ort )0, dbValue, SQL_C_DOUBLE);
countSet.Close();
return (long )dbValue.m_dblVal;
}
catch(CException *e)
{
e->ReportError();
e->Delete();
return -1;
}
}
same very easily with very few lines of code. Depending upon your query type
you can make the query return any value with or without using a class structure.
For e.g. If all you ever want from this kind of function is a count, it does not make
too much sense to create a class. You need to be more specific in your need
before you can create a class.
For the above mentioned query, I find this function to be the most convenient. It
is assumed here that the tablename you are querying is accessible from pointer
to recordset. If this is not the case, you need to somehow provide the complete
SQL query to the function before it executes countSet.Open ...
//It will return current record count for any open record set. Since this value is not //ODBC-layer dependant, it is generally lot more reliable
long GetRecordsetCount(CRecords
{
try
{
CRecordset countSet(pSet->m_pDatabase
CString strQuery;
CString strTableName;
CDBVariant dbValue;
strTableName = pSet->GetDefaultSQL();
// No reserved words should already be in use
ASSERT(strTableName.Find("
ASSERT(strTableName.Find("
ASSERT(strTableName.Find("
strQuery.Format("SELECT COUNT(*) CNT FROM %s",strTableName);
countSet.m_strFilter = pSet->m_strFilter;
countSet.Open(CRecordset::
countSet.GetFieldValue((sh
countSet.Close();
return (long )dbValue.m_dblVal;
}
catch(CException *e)
{
e->ReportError();
e->Delete();
return -1;
}
}
You can do it but, it takes some work. The thing is that MFC provides some classes for this. Recordsets aren't the greatest classes around but, they do save some work. If you want to get return values you'll have to write a class similar to a recordset. If you really want to I'll give you some code but, most everything you'll do you can do with a recordset.