Discussion:
CDatabase CRecordset - How to get the number of rows?
(too old to reply)
David++
2005-06-09 15:19:02 UTC
Permalink
Hi there,

I'm using Visual C++6 and MFC to connect to a database. So far I have just
been able to connect to the database. I want to count the number of rows in
the database so I can see if there is any data in it. All I want to do is get
the number of rows if possible. I dont need to pass any of the actual data
(if there is any). I've been using the CDatabase class to connect to the
Database and have tried a few things using the CRecordset class to try and
return the number of rows. Here is a cut down version of my code in which I
have removed all the try catch blocks for clarity -

CDatabase db;
db.Open(connectionString);

CRecordset rs(&db);
rs.Open(CRecordset::forwardOnly,_T( "SELECT COUNT (*) FROM Records" ) );

long recordCount = 0;
recordCount = rs.GetRecordCount();

However, when I check the value of recordCount it always returns 1 even when
there are none or many rows in the table.

Any tips on how to do this is much appreciated!

Thanks,

David
Bill Thompson
2005-06-09 20:23:52 UTC
Permalink
Post by David++
Hi there,
I'm using Visual C++6 and MFC to connect to a database. So far I have just
been able to connect to the database. I want to count the number of rows in
the database so I can see if there is any data in it. All I want to do is get
the number of rows if possible. I dont need to pass any of the actual data
(if there is any). I've been using the CDatabase class to connect to the
Database and have tried a few things using the CRecordset class to try and
return the number of rows. Here is a cut down version of my code in which I
have removed all the try catch blocks for clarity -
CDatabase db;
db.Open(connectionString);
CRecordset rs(&db);
rs.Open(CRecordset::forwardOnly,_T( "SELECT COUNT (*) FROM Records" ) );
long recordCount = 0;
recordCount = rs.GetRecordCount();
However, when I check the value of recordCount it always returns 1 even when
there are none or many rows in the table.
Any tips on how to do this is much appreciated!
Thanks,
David
the GetRecordCount() indicates you have to perform a MoveLast() prior to
getting the record count.

Obviously this is a problem for a forward only recordset. Can't suggest
anything else without knowing more details.

I understand that DAO will become deprecated at some point and that ADO is
the way to go.
Gert
2005-06-09 20:44:18 UTC
Permalink
Post by David++
rs.Open(CRecordset::forwardOnly,_T( "SELECT COUNT (*) FROM Records" ) );
COUNT(*) will always return 1 row with 1 column, and that doesn't depend
on the number of rows inside Records - the VALUE of the one column WILL
depend on the number of records. So the answer of "1" is correct.

Gert
David++
2005-06-09 21:29:02 UTC
Permalink
Hi,

Thanks for both your answers. I've changed my code a bit to this -

CRecordset rs(&db);
rs.Open(CRecordset::forwardOnly,_T( "SELECT * FROM Records" ) );

int count = 0;
while (!rs.IsEOF())
{
count += 1;
rs.MoveNext();
}

I've now dropped the COUNT (*) and have used just * in the SQL Statement. It
seems to be working a little better but i cant fully check it as I'm on my
home computer now. Interestingly, if I use the MoveLast() function I get a
runtime Debug Assertion failure?

Well, thanks once again for your help and views. I'll post any outcomes I
make,

Best,
David
Roy Fine
2005-06-10 02:25:04 UTC
Permalink
Post by David++
Hi,
Thanks for both your answers. I've changed my code a bit to this -
CRecordset rs(&db);
rs.Open(CRecordset::forwardOnly,_T( "SELECT * FROM Records" ) );
int count = 0;
while (!rs.IsEOF())
{
count += 1;
rs.MoveNext();
}
I've now dropped the COUNT (*) and have used just * in the SQL Statement. It
seems to be working a little better but i cant fully check it as I'm on my
home computer now. Interestingly, if I use the MoveLast() function I get a
runtime Debug Assertion failure?
Well, thanks once again for your help and views. I'll post any outcomes I
make,
Best,
David
What you have is most inefficient method available for determining the
number of rows in a cursor - by fetching each row, and incrementing a
counter. Consider the impact of moving the database to a host on the
network (ever better, to a host on an internet). In this case, network
delays kill performance.

Consider something like this (which pushes most of the work to the database
server and fetches one row with one field):

CRecordset rs(&db);
rs.Open(CRecordset::ForwardOnly,"Select count(*) from
Records",CRecordset::ReadOnly);
CDBVariant vtval;
rs.GetFieldValue((short)0,vtval);
int rowcount = vtval.m_lVal;
rs.Close();


regards
Roy Fine
David++
2005-06-10 12:48:03 UTC
Permalink
Ok, I tried this way but now instead of getting 3 rows returned (which is how
many rows there are in my table), I now get 14549040 rows returned? Hmm, any
ideas?

Thanks,

David
Post by Roy Fine
Consider something like this (which pushes most of the work to the database
CRecordset rs(&db);
rs.Open(CRecordset::ForwardOnly,"Select count(*) from
Records",CRecordset::ReadOnly);
CDBVariant vtval;
rs.GetFieldValue((short)0,vtval);
int rowcount = vtval.m_lVal;
rs.Close();
regards
Roy Fine
Roy Fine
2005-06-10 12:57:38 UTC
Permalink
David

show some code -- the count function is a single row function - it can not
return anything but ONE row with one scalar type.

the snip that I provided has no error checking - specifically check the
datatype of the variant - and if necessary convert it to a long/integer.

roy
Post by David++
Ok, I tried this way but now instead of getting 3 rows returned (which is how
many rows there are in my table), I now get 14549040 rows returned? Hmm, any
ideas?
Thanks,
David
Post by Roy Fine
Consider something like this (which pushes most of the work to the database
CRecordset rs(&db);
rs.Open(CRecordset::ForwardOnly,"Select count(*) from
Records",CRecordset::ReadOnly);
CDBVariant vtval;
rs.GetFieldValue((short)0,vtval);
int rowcount = vtval.m_lVal;
rs.Close();
regards
Roy Fine
David++
2005-06-10 13:44:06 UTC
Permalink
Hi Roy,

This is the code I have so far -

CRecordset rs(&db);

rs.Open(CRecordset::forwardOnly,"SELECT * FROM Records",CRecordset::readOnly);

CDBVariant vtval;
rs.GetFieldValue((short)0,vtval);
int rowcount = vtval.m_lVal;

char buffer[10];
_itoa(rowcount,buffer,10);

FILE *f;
f = fopen("Rows.txt","w");
fprintf(f,"Rows: ");
fprintf(f, buffer);

fclose(f);
rs.Close();

I'm printing the result to a text file for debugging purposes. The database
I'm using was made in Access and the fields are all of type 'Text' so I guess
its returning a char here? That may be the problem

Thanks again,

David
Post by Roy Fine
David
show some code -- the count function is a single row function - it can not
return anything but ONE row with one scalar type.
the snip that I provided has no error checking - specifically check the
datatype of the variant - and if necessary convert it to a long/integer.
roy
Post by David++
Ok, I tried this way but now instead of getting 3 rows returned (which is
how
Post by David++
many rows there are in my table), I now get 14549040 rows returned? Hmm,
any
Post by David++
ideas?
Thanks,
David
Post by Roy Fine
Consider something like this (which pushes most of the work to the
database
Post by David++
Post by Roy Fine
CRecordset rs(&db);
rs.Open(CRecordset::ForwardOnly,"Select count(*) from
Records",CRecordset::ReadOnly);
CDBVariant vtval;
rs.GetFieldValue((short)0,vtval);
int rowcount = vtval.m_lVal;
rs.Close();
regards
Roy Fine
Roy Fine
2005-06-11 10:55:53 UTC
Permalink
Post by David++
Hi Roy,
This is the code I have so far -
CRecordset rs(&db);
rs.Open(CRecordset::forwardOnly,"SELECT * FROM
Records",CRecordset::readOnly);
NO! -- the SQL command should be "Select Count(*) FROM Recrds"

regards
Roy
David++
2005-06-13 08:47:01 UTC
Permalink
Hi Roy :-)

It works now! Thankyou very, very much for your help! If I could I woyuld
buy you a beer,

All the best,
David
Post by David++
Post by David++
Hi Roy,
This is the code I have so far -
CRecordset rs(&db);
rs.Open(CRecordset::forwardOnly,"SELECT * FROM
Records",CRecordset::readOnly);
NO! -- the SQL command should be "Select Count(*) FROM Recrds"
regards
Roy
Roy Fine
2005-06-13 10:48:49 UTC
Permalink
david,

glad to be of assistance....

rlf
Post by David++
Hi Roy :-)
It works now! Thankyou very, very much for your help! If I could I woyuld
buy you a beer,
All the best,
David
Post by David++
Post by David++
Hi Roy,
This is the code I have so far -
CRecordset rs(&db);
rs.Open(CRecordset::forwardOnly,"SELECT * FROM
Records",CRecordset::readOnly);
NO! -- the SQL command should be "Select Count(*) FROM Recrds"
regards
Roy
David++
2005-06-13 16:15:02 UTC
Permalink
Hello Again,

Damn, I thought I had nailed this one. Looks like I spoke too soon as usual.
I'm now testing my DLL with the real database. Its an Oracle SQL Database.
I'm able to connect to it and perform my slow algorithm (yes, back to that
one) and it returns around 87,000 rows which is correct. However, as you are
aware it takes too long to fetch all those rows one at a time. For some
reason the fast algorithm doesnt work on this new database and returns 0
rows. Everything is the same as before and I've only changed the connection
string to suit this new database. I know I can connect as the slow algorithm
eventually returns the result. But how come the fast algorithm returns zero
again? I'm pretty sure the ODBC Driver for Oracle is configured etc.. Sorry
to bother you again, I've been picking away at this all day with no progress.

Any opinions welcome,

Many Thanks,
David
Post by Roy Fine
david,
glad to be of assistance....
rlf
Post by David++
Hi Roy :-)
It works now! Thankyou very, very much for your help! If I could I woyuld
buy you a beer,
All the best,
David
Post by David++
Post by David++
Hi Roy,
This is the code I have so far -
CRecordset rs(&db);
rs.Open(CRecordset::forwardOnly,"SELECT * FROM
Records",CRecordset::readOnly);
NO! -- the SQL command should be "Select Count(*) FROM Recrds"
regards
Roy
Roy Fine
2005-06-13 19:23:34 UTC
Permalink
David,

show the connection (CDatabase object) and the CRecordset open and fetch
code. I have a couple of Oracle instances that I can test against -

One Note - we might be well advised to get the snippet working in a minimal
MFC app, then move it to a DLL when all is working. Let's debug one step at
a time.


regards
Roy Fine
Post by David++
Hello Again,
Damn, I thought I had nailed this one. Looks like I spoke too soon as usual.
I'm now testing my DLL with the real database. Its an Oracle SQL Database.
I'm able to connect to it and perform my slow algorithm (yes, back to that
one) and it returns around 87,000 rows which is correct. However, as you are
aware it takes too long to fetch all those rows one at a time. For some
reason the fast algorithm doesnt work on this new database and returns 0
rows. Everything is the same as before and I've only changed the connection
string to suit this new database. I know I can connect as the slow algorithm
eventually returns the result. But how come the fast algorithm returns zero
again? I'm pretty sure the ODBC Driver for Oracle is configured etc.. Sorry
to bother you again, I've been picking away at this all day with no progress.
Any opinions welcome,
Many Thanks,
David
Post by Roy Fine
david,
glad to be of assistance....
rlf
Post by David++
Hi Roy :-)
It works now! Thankyou very, very much for your help! If I could I woyuld
buy you a beer,
All the best,
David
Post by David++
Post by David++
Hi Roy,
This is the code I have so far -
CRecordset rs(&db);
rs.Open(CRecordset::forwardOnly,"SELECT * FROM
Records",CRecordset::readOnly);
NO! -- the SQL command should be "Select Count(*) FROM Recrds"
regards
Roy
David++
2005-06-14 08:32:02 UTC
Permalink
Hi Roy,

Thanks for your continued help, Here is my code -


// Declare our CDatabase object
CDatabase dbSQL;
dbSQL.SetQueryTimeout(60);
BOOL bSuccess;

// Declare a long to hold the row count for the fast method
long rowcountSQL = 0;
// Declare a long to hold the row count for the slow method
long count = 0;

try
{
bSuccess = dbSQL.Open(connect);
}

catch(CDBException)
{
// DB Connection Failure
//SetFailureBoolean(0);
//SetMessageString(0);
}

if(bSuccess)
{
try
{
// Set failure bool to false
// This is used to control user messages i.e. success / fail
//SetFailureBoolean(1);

// Declare and open our Recordset
CRecordset rs(&dbSQL);
rs.Open(CRecordset::forwardOnly,dataStr,CRecordset::readOnly);
CDBVariant vtval;
rs.GetFieldValue((long)0,vtval);
rowcountSQL = vtval.m_lVal;

/*
//This can be used for debugging to a file
char buffer[10];
_ltoa(rowcountSQL, buffer, 10);

FILE *f;
f = fopen("Debug.txt", "w");
fprintf(f, buffer);
fclose(f);
*/


// This is the slow method to count the rows
// This works but is too slow
/*
count = 0;
while(!rs.IsEOF())
{
count +=1;
rs.MoveNext();
}
*/

// Close Recordset
rs.Close();

}
catch(CDBException)
{
// SQL Error
//SetFailureBoolean(0);
//SetMessageString(1);
}
}

dbSQL.Close();
// Here I pass back the row count to the calling function
return(rowcountSQL);
}

Many thanks for any advice,

Best Regards,
David
Post by Roy Fine
David,
show the connection (CDatabase object) and the CRecordset open and fetch
code. I have a couple of Oracle instances that I can test against -
One Note - we might be well advised to get the snippet working in a minimal
MFC app, then move it to a DLL when all is working. Let's debug one step at
a time.
regards
Roy Fine
Post by David++
Hello Again,
Damn, I thought I had nailed this one. Looks like I spoke too soon as
usual.
Post by David++
I'm now testing my DLL with the real database. Its an Oracle SQL Database.
I'm able to connect to it and perform my slow algorithm (yes, back to that
one) and it returns around 87,000 rows which is correct. However, as you
are
Post by David++
aware it takes too long to fetch all those rows one at a time. For some
reason the fast algorithm doesnt work on this new database and returns 0
rows. Everything is the same as before and I've only changed the
connection
Post by David++
string to suit this new database. I know I can connect as the slow
algorithm
Post by David++
eventually returns the result. But how come the fast algorithm returns
zero
Post by David++
again? I'm pretty sure the ODBC Driver for Oracle is configured etc..
Sorry
Post by David++
to bother you again, I've been picking away at this all day with no
progress.
Post by David++
Any opinions welcome,
Many Thanks,
David
Post by Roy Fine
david,
glad to be of assistance....
rlf
Post by David++
Hi Roy :-)
It works now! Thankyou very, very much for your help! If I could I
woyuld
Post by David++
Post by Roy Fine
Post by David++
buy you a beer,
All the best,
David
Post by David++
Post by David++
Hi Roy,
This is the code I have so far -
CRecordset rs(&db);
rs.Open(CRecordset::forwardOnly,"SELECT * FROM
Records",CRecordset::readOnly);
NO! -- the SQL command should be "Select Count(*) FROM Recrds"
regards
Roy
Roy Fine
2005-06-14 12:00:50 UTC
Permalink
David,

pardon the top posting, but:

What is the value of dataStr in the CRecordset::Open call. If dataStr is
not "Select count(*) from Table" then you will not get the correct results.


Have alook at the MSDN docs at the CRecordset::GetFieldValue. there is no
method that takes a long as the first argument, so the following makes no
Post by David++
rs.GetFieldValue((long)0,vtval);
I would recommend changing to something like this:
rs.GetFieldValue((short)0,vtval,SQL_C_SLONG);

regards
Roy Fine
Post by David++
Hi Roy,
Thanks for your continued help, Here is my code -
// Declare our CDatabase object
CDatabase dbSQL;
dbSQL.SetQueryTimeout(60);
BOOL bSuccess;
// Declare a long to hold the row count for the fast method
long rowcountSQL = 0;
// Declare a long to hold the row count for the slow method
long count = 0;
try
{
bSuccess = dbSQL.Open(connect);
}
catch(CDBException)
{
// DB Connection Failure
//SetFailureBoolean(0);
//SetMessageString(0);
}
if(bSuccess)
{
try
{
// Set failure bool to false
// This is used to control user messages i.e. success / fail
//SetFailureBoolean(1);
// Declare and open our Recordset
CRecordset rs(&dbSQL);
rs.Open(CRecordset::forwardOnly,dataStr,CRecordset::readOnly);
CDBVariant vtval;
rs.GetFieldValue((long)0,vtval);
rowcountSQL = vtval.m_lVal;
/*
//This can be used for debugging to a file
char buffer[10];
_ltoa(rowcountSQL, buffer, 10);
FILE *f;
f = fopen("Debug.txt", "w");
fprintf(f, buffer);
fclose(f);
*/
// This is the slow method to count the rows
// This works but is too slow
/*
count = 0;
while(!rs.IsEOF())
{
count +=1;
rs.MoveNext();
}
*/
// Close Recordset
rs.Close();
}
catch(CDBException)
{
// SQL Error
//SetFailureBoolean(0);
//SetMessageString(1);
}
}
dbSQL.Close();
// Here I pass back the row count to the calling function
return(rowcountSQL);
}
Many thanks for any advice,
Best Regards,
David
Post by Roy Fine
David,
show the connection (CDatabase object) and the CRecordset open and fetch
code. I have a couple of Oracle instances that I can test against -
One Note - we might be well advised to get the snippet working in a minimal
MFC app, then move it to a DLL when all is working. Let's debug one step at
a time.
regards
Roy Fine
Post by David++
Hello Again,
Damn, I thought I had nailed this one. Looks like I spoke too soon as
usual.
Post by David++
I'm now testing my DLL with the real database. Its an Oracle SQL Database.
I'm able to connect to it and perform my slow algorithm (yes, back to that
one) and it returns around 87,000 rows which is correct. However, as you
are
Post by David++
aware it takes too long to fetch all those rows one at a time. For some
reason the fast algorithm doesnt work on this new database and returns 0
rows. Everything is the same as before and I've only changed the
connection
Post by David++
string to suit this new database. I know I can connect as the slow
algorithm
Post by David++
eventually returns the result. But how come the fast algorithm returns
zero
Post by David++
again? I'm pretty sure the ODBC Driver for Oracle is configured etc..
Sorry
Post by David++
to bother you again, I've been picking away at this all day with no
progress.
Post by David++
Any opinions welcome,
Many Thanks,
David
Post by Roy Fine
david,
glad to be of assistance....
rlf
Post by David++
Hi Roy :-)
It works now! Thankyou very, very much for your help! If I could I
woyuld
Post by David++
Post by Roy Fine
Post by David++
buy you a beer,
All the best,
David
Post by David++
Post by David++
Hi Roy,
This is the code I have so far -
CRecordset rs(&db);
rs.Open(CRecordset::forwardOnly,"SELECT * FROM
Records",CRecordset::readOnly);
NO! -- the SQL command should be "Select Count(*) FROM Recrds"
regards
Roy
David++
2005-06-14 12:46:02 UTC
Permalink
Roy,

You are an absolute genius!

I replaced this line - rs.GetFieldValue((long)0,vtval);

with this line - rs.GetFieldValue((short)0,vtval,SQL_C_SLONG);

And now it works great! I think in my naivety I was trying to get the
GetFieldValue() to return a long, which obviously isnt the right way to do it
(can you tell I'm new to this), however your method works flawlessly! I
breathe a big sigh of relief over here.

Many many thanks for saving my bacon once again! Your a swell guy!

All the very best,

Best Regards,
David
Post by Roy Fine
David,
What is the value of dataStr in the CRecordset::Open call. If dataStr is
not "Select count(*) from Table" then you will not get the correct results.
Have alook at the MSDN docs at the CRecordset::GetFieldValue. there is no
method that takes a long as the first argument, so the following makes no
Post by David++
rs.GetFieldValue((long)0,vtval);
rs.GetFieldValue((short)0,vtval,SQL_C_SLONG);
regards
Roy Fine
Post by David++
Hi Roy,
Thanks for your continued help, Here is my code -
// Declare our CDatabase object
CDatabase dbSQL;
dbSQL.SetQueryTimeout(60);
BOOL bSuccess;
// Declare a long to hold the row count for the fast method
long rowcountSQL = 0;
// Declare a long to hold the row count for the slow method
long count = 0;
try
{
bSuccess = dbSQL.Open(connect);
}
catch(CDBException)
{
// DB Connection Failure
//SetFailureBoolean(0);
//SetMessageString(0);
}
if(bSuccess)
{
try
{
// Set failure bool to false
// This is used to control user messages i.e. success / fail
//SetFailureBoolean(1);
// Declare and open our Recordset
CRecordset rs(&dbSQL);
rs.Open(CRecordset::forwardOnly,dataStr,CRecordset::readOnly);
CDBVariant vtval;
rs.GetFieldValue((long)0,vtval);
rowcountSQL = vtval.m_lVal;
/*
//This can be used for debugging to a file
char buffer[10];
_ltoa(rowcountSQL, buffer, 10);
FILE *f;
f = fopen("Debug.txt", "w");
fprintf(f, buffer);
fclose(f);
*/
// This is the slow method to count the rows
// This works but is too slow
/*
count = 0;
while(!rs.IsEOF())
{
count +=1;
rs.MoveNext();
}
*/
// Close Recordset
rs.Close();
}
catch(CDBException)
{
// SQL Error
//SetFailureBoolean(0);
//SetMessageString(1);
}
}
dbSQL.Close();
// Here I pass back the row count to the calling function
return(rowcountSQL);
}
Many thanks for any advice,
Best Regards,
David
Post by Roy Fine
David,
show the connection (CDatabase object) and the CRecordset open and fetch
code. I have a couple of Oracle instances that I can test against -
One Note - we might be well advised to get the snippet working in a
minimal
Post by David++
Post by Roy Fine
MFC app, then move it to a DLL when all is working. Let's debug one
step at
Post by David++
Post by Roy Fine
a time.
regards
Roy Fine
Post by David++
Hello Again,
Damn, I thought I had nailed this one. Looks like I spoke too soon as
usual.
Post by David++
I'm now testing my DLL with the real database. Its an Oracle SQL
Database.
Post by David++
Post by Roy Fine
Post by David++
I'm able to connect to it and perform my slow algorithm (yes, back to
that
Post by David++
Post by Roy Fine
Post by David++
one) and it returns around 87,000 rows which is correct. However, as
you
Post by David++
Post by Roy Fine
are
Post by David++
aware it takes too long to fetch all those rows one at a time. For
some
Post by David++
Post by Roy Fine
Post by David++
reason the fast algorithm doesnt work on this new database and returns
0
Post by David++
Post by Roy Fine
Post by David++
rows. Everything is the same as before and I've only changed the
connection
Post by David++
string to suit this new database. I know I can connect as the slow
algorithm
Post by David++
eventually returns the result. But how come the fast algorithm returns
zero
Post by David++
again? I'm pretty sure the ODBC Driver for Oracle is configured etc..
Sorry
Post by David++
to bother you again, I've been picking away at this all day with no
progress.
Post by David++
Any opinions welcome,
Many Thanks,
David
Post by Roy Fine
david,
glad to be of assistance....
rlf
Post by David++
Hi Roy :-)
It works now! Thankyou very, very much for your help! If I could I
woyuld
Post by David++
Post by Roy Fine
Post by David++
buy you a beer,
All the best,
David
Post by David++
Post by David++
Hi Roy,
This is the code I have so far -
CRecordset rs(&db);
rs.Open(CRecordset::forwardOnly,"SELECT * FROM
Records",CRecordset::readOnly);
NO! -- the SQL command should be "Select Count(*) FROM Recrds"
regards
Roy
Roy Fine
2005-06-14 16:16:14 UTC
Permalink
David

happy to help -- now all that is left to attend to is the "beer". :)

rlf
Post by David++
Roy,
You are an absolute genius!
I replaced this line - rs.GetFieldValue((long)0,vtval);
with this line - rs.GetFieldValue((short)0,vtval,SQL_C_SLONG);
And now it works great! I think in my naivety I was trying to get the
GetFieldValue() to return a long, which obviously isnt the right way to do it
(can you tell I'm new to this), however your method works flawlessly! I
breathe a big sigh of relief over here.
Many many thanks for saving my bacon once again! Your a swell guy!
All the very best,
Best Regards,
David
Post by Roy Fine
David,
What is the value of dataStr in the CRecordset::Open call. If dataStr is
not "Select count(*) from Table" then you will not get the correct results.
Have alook at the MSDN docs at the CRecordset::GetFieldValue. there is no
method that takes a long as the first argument, so the following makes no
Post by David++
rs.GetFieldValue((long)0,vtval);
rs.GetFieldValue((short)0,vtval,SQL_C_SLONG);
regards
Roy Fine
Post by David++
Hi Roy,
Thanks for your continued help, Here is my code -
// Declare our CDatabase object
CDatabase dbSQL;
dbSQL.SetQueryTimeout(60);
BOOL bSuccess;
// Declare a long to hold the row count for the fast method
long rowcountSQL = 0;
// Declare a long to hold the row count for the slow method
long count = 0;
try
{
bSuccess = dbSQL.Open(connect);
}
catch(CDBException)
{
// DB Connection Failure
//SetFailureBoolean(0);
//SetMessageString(0);
}
if(bSuccess)
{
try
{
// Set failure bool to false
// This is used to control user messages i.e. success / fail
//SetFailureBoolean(1);
// Declare and open our Recordset
CRecordset rs(&dbSQL);
rs.Open(CRecordset::forwardOnly,dataStr,CRecordset::readOnly);
CDBVariant vtval;
rs.GetFieldValue((long)0,vtval);
rowcountSQL = vtval.m_lVal;
/*
//This can be used for debugging to a file
char buffer[10];
_ltoa(rowcountSQL, buffer, 10);
FILE *f;
f = fopen("Debug.txt", "w");
fprintf(f, buffer);
fclose(f);
*/
// This is the slow method to count the rows
// This works but is too slow
/*
count = 0;
while(!rs.IsEOF())
{
count +=1;
rs.MoveNext();
}
*/
// Close Recordset
rs.Close();
}
catch(CDBException)
{
// SQL Error
//SetFailureBoolean(0);
//SetMessageString(1);
}
}
dbSQL.Close();
// Here I pass back the row count to the calling function
return(rowcountSQL);
}
Many thanks for any advice,
Best Regards,
David
Post by Roy Fine
David,
show the connection (CDatabase object) and the CRecordset open and fetch
code. I have a couple of Oracle instances that I can test against -
One Note - we might be well advised to get the snippet working in a
minimal
Post by David++
Post by Roy Fine
MFC app, then move it to a DLL when all is working. Let's debug one
step at
Post by David++
Post by Roy Fine
a time.
regards
Roy Fine
Post by David++
Hello Again,
Damn, I thought I had nailed this one. Looks like I spoke too soon as
usual.
Post by David++
I'm now testing my DLL with the real database. Its an Oracle SQL
Database.
Post by David++
Post by Roy Fine
Post by David++
I'm able to connect to it and perform my slow algorithm (yes, back to
that
Post by David++
Post by Roy Fine
Post by David++
one) and it returns around 87,000 rows which is correct. However, as
you
Post by David++
Post by Roy Fine
are
Post by David++
aware it takes too long to fetch all those rows one at a time. For
some
Post by David++
Post by Roy Fine
Post by David++
reason the fast algorithm doesnt work on this new database and returns
0
Post by David++
Post by Roy Fine
Post by David++
rows. Everything is the same as before and I've only changed the
connection
Post by David++
string to suit this new database. I know I can connect as the slow
algorithm
Post by David++
eventually returns the result. But how come the fast algorithm returns
zero
Post by David++
again? I'm pretty sure the ODBC Driver for Oracle is configured etc..
Sorry
Post by David++
to bother you again, I've been picking away at this all day with no
progress.
Post by David++
Any opinions welcome,
Many Thanks,
David
Post by Roy Fine
david,
glad to be of assistance....
rlf
Post by David++
Hi Roy :-)
It works now! Thankyou very, very much for your help! If I could I
woyuld
Post by David++
Post by Roy Fine
Post by David++
buy you a beer,
All the best,
David
Post by David++
Post by David++
Hi Roy,
This is the code I have so far -
CRecordset rs(&db);
rs.Open(CRecordset::forwardOnly,"SELECT * FROM
Records",CRecordset::readOnly);
NO! -- the SQL command should be "Select Count(*) FROM Recrds"
regards
Roy
David++
2005-06-17 17:14:04 UTC
Permalink
Hi Roy,

Its Friday night, hope the beer is cold where you are ;-)

All the best,
David
Post by Roy Fine
David
happy to help -- now all that is left to attend to is the "beer". :)
rlf
Post by David++
Roy,
You are an absolute genius!
I replaced this line - rs.GetFieldValue((long)0,vtval);
with this line - rs.GetFieldValue((short)0,vtval,SQL_C_SLONG);
And now it works great! I think in my naivety I was trying to get the
GetFieldValue() to return a long, which obviously isnt the right way to do
it
Post by David++
(can you tell I'm new to this), however your method works flawlessly! I
breathe a big sigh of relief over here.
Many many thanks for saving my bacon once again! Your a swell guy!
All the very best,
Best Regards,
David
Post by Roy Fine
David,
What is the value of dataStr in the CRecordset::Open call. If dataStr
is
Post by David++
Post by Roy Fine
not "Select count(*) from Table" then you will not get the correct
results.
Post by David++
Post by Roy Fine
Have alook at the MSDN docs at the CRecordset::GetFieldValue. there is
no
Post by David++
Post by Roy Fine
method that takes a long as the first argument, so the following makes
no
Post by David++
Post by Roy Fine
Post by David++
rs.GetFieldValue((long)0,vtval);
rs.GetFieldValue((short)0,vtval,SQL_C_SLONG);
regards
Roy Fine
Post by David++
Hi Roy,
Thanks for your continued help, Here is my code -
// Declare our CDatabase object
CDatabase dbSQL;
dbSQL.SetQueryTimeout(60);
BOOL bSuccess;
// Declare a long to hold the row count for the fast method
long rowcountSQL = 0;
// Declare a long to hold the row count for the slow method
long count = 0;
try
{
bSuccess = dbSQL.Open(connect);
}
catch(CDBException)
{
// DB Connection Failure
//SetFailureBoolean(0);
//SetMessageString(0);
}
if(bSuccess)
{
try
{
// Set failure bool to false
// This is used to control user messages i.e. success / fail
//SetFailureBoolean(1);
// Declare and open our Recordset
CRecordset rs(&dbSQL);
rs.Open(CRecordset::forwardOnly,dataStr,CRecordset::readOnly);
CDBVariant vtval;
rs.GetFieldValue((long)0,vtval);
rowcountSQL = vtval.m_lVal;
/*
//This can be used for debugging to a file
char buffer[10];
_ltoa(rowcountSQL, buffer, 10);
FILE *f;
f = fopen("Debug.txt", "w");
fprintf(f, buffer);
fclose(f);
*/
// This is the slow method to count the rows
// This works but is too slow
/*
count = 0;
while(!rs.IsEOF())
{
count +=1;
rs.MoveNext();
}
*/
// Close Recordset
rs.Close();
}
catch(CDBException)
{
// SQL Error
//SetFailureBoolean(0);
//SetMessageString(1);
}
}
dbSQL.Close();
// Here I pass back the row count to the calling function
return(rowcountSQL);
}
Many thanks for any advice,
Best Regards,
David
Post by Roy Fine
David,
show the connection (CDatabase object) and the CRecordset open and
fetch
Post by David++
Post by Roy Fine
Post by David++
Post by Roy Fine
code. I have a couple of Oracle instances that I can test against -
One Note - we might be well advised to get the snippet working in a
minimal
Post by David++
Post by Roy Fine
MFC app, then move it to a DLL when all is working. Let's debug one
step at
Post by David++
Post by Roy Fine
a time.
regards
Roy Fine
Post by David++
Hello Again,
Damn, I thought I had nailed this one. Looks like I spoke too soon
as
Post by David++
Post by Roy Fine
Post by David++
Post by Roy Fine
usual.
Post by David++
I'm now testing my DLL with the real database. Its an Oracle SQL
Database.
Post by David++
Post by Roy Fine
Post by David++
I'm able to connect to it and perform my slow algorithm (yes, back
to
Post by David++
Post by Roy Fine
that
Post by David++
Post by Roy Fine
Post by David++
one) and it returns around 87,000 rows which is correct. However,
as
Post by David++
Post by Roy Fine
you
Post by David++
Post by Roy Fine
are
Post by David++
aware it takes too long to fetch all those rows one at a time. For
some
Post by David++
Post by Roy Fine
Post by David++
reason the fast algorithm doesnt work on this new database and
returns
Post by David++
Post by Roy Fine
0
Post by David++
Post by Roy Fine
Post by David++
rows. Everything is the same as before and I've only changed the
connection
Post by David++
string to suit this new database. I know I can connect as the slow
algorithm
Post by David++
eventually returns the result. But how come the fast algorithm
returns
Post by David++
Post by Roy Fine
Post by David++
Post by Roy Fine
zero
Post by David++
again? I'm pretty sure the ODBC Driver for Oracle is configured
etc..
Post by David++
Post by Roy Fine
Post by David++
Post by Roy Fine
Sorry
Post by David++
to bother you again, I've been picking away at this all day with
no
Post by David++
Post by Roy Fine
Post by David++
Post by Roy Fine
progress.
Post by David++
Any opinions welcome,
Many Thanks,
David
Post by Roy Fine
david,
glad to be of assistance....
rlf
Post by David++
Hi Roy :-)
It works now! Thankyou very, very much for your help! If I
could I
Post by David++
Post by Roy Fine
Post by David++
Post by Roy Fine
woyuld
Post by David++
Post by Roy Fine
Post by David++
buy you a beer,
All the best,
David
Post by David++
Post by David++
Hi Roy,
This is the code I have so far -
CRecordset rs(&db);
rs.Open(CRecordset::forwardOnly,"SELECT * FROM
Records",CRecordset::readOnly);
NO! -- the SQL command should be "Select Count(*) FROM
Recrds"
Post by David++
Post by Roy Fine
Post by David++
Post by Roy Fine
Post by David++
Post by Roy Fine
Post by David++
Post by David++
regards
Roy
Paul S. Ganney
2005-06-10 08:44:10 UTC
Permalink
If you want to do a lot of this counting malarky, then I posted a class
to the code project that implements it all in a nice and easy fashion.

http://www.codeproject.com/database/CountSet.asp

Paul.
Loading...