sql-serverdelphidatasetmemory-managementrecord-count

SDAC -RecordCount and FetchAll


I am using SDAC components to query a SQL Server 2008 database. It has a recordcountproperty as all datasets do and it also has the FetchAll property (which I think it is called packedrecords on clientdatasets). Said that, I got a few questions:

1 - If I set FetchAll = True the recordcount property returns ok. But in this case, when I have a large database and my query returns a lot of lines, sometimes the memory grows a lot (because it is fetching all data to get the recordcount of course).

2 - If I set FetchAll = False, the recordcount returns -1 and the memory does not grow. But I really need the recordcount. And I also wanna create a generic function for this, so I dont have to change all my existent queries.

What can I do to have the recordcount working and the memory usage of the application low in this case?

Please, do not post that I dont need recordcount (or that I should use EOF and BOF) because I really do and this is not the question.

I thought about using a query to determine the recordcount, but it has some problems since my query is going to be executed twice (1 for recordcount, 1 for data)

EDIT

@Johan pointed out a good solution, and it seems to work. Can anybody confirm this? I am using 1 TMSCconnection for every TMSQuery (because i am using threads), so I dont think this will be a problem, will it?

  MSQuery1.FetchAll := False;
  MSQuery1.FetchRows := 10;
  MSQuery1.SQL.Text := 'select * from cidade';
  MSQuery1.Open;
  ShowMessage(IntToStr(MSQuery1.RecordCount)); //returns 10
  MSQuery1.Close;

  MSQuery2.SQL.Text := 'SELECT @@rowcount AS num_of_rows';
  MSQuery2.Open;
  ShowMessage(MSQuery2.FieldByName('num_of_rows').AsString); //returns 289

EDIT 2*

MSQuery1 must be closed, or MSQuery2 will not return the num_of_rows. Why is that?

  MSQuery1.FetchAll := False;
  MSQuery1.FetchRows := 10;
  MSQuery1.SQL.Text := 'select * from cidade';
  MSQuery1.Open;
  ShowMessage(IntToStr(MSQuery1.RecordCount)); //returns 10
  //MSQuery1.Close; <<commented

  MSQuery2.SQL.Text := 'SELECT @@rowcount AS num_of_rows';
  MSQuery2.Open;
  ShowMessage(MSQuery2.FieldByName('num_of_rows').AsString); //returns 0

Solution

  • Run your query as normal, than close the query

    MSQuery1.SQL.Text := 'select * from cidade';     
    MSQuery1.Open;     
    MSQuery1.Close;  
    

    You need the close otherwise SQL-server has not closed the cursor yet, and will not register the query as 'completed'.

    and run the following query right afterwards:

    SELECT @@rowcount AS num_of_rows
    

    This will select the total number of rows your last select read.
    It will also select the number of rows your update/delete/insert statement affected.

    See: http://technet.microsoft.com/en-us/library/ms187316.aspx

    Note that this variable is per connection, so queries in other connections do not affect you.