I am trying to get the number of rows returned in a query. The while loop looping through the results works, but for some reason the sqlsrv_num_rows does not return any valu
I agree with Jack. I count(*) is a quick way to get a row count, however, you might have to do a clustered index scan. For small data sets, this is not an issue.
On the other hand, you can use the system catalog views. However, these get updated per some background thread. For multi-terabyte data sets, a catalog lookup might be quicker.
Depending upon system events, the count may or may not be accurate.
http://sqlblog.com/blogs/kalen_delaney/archive/2009/12/07/how-many-rows.aspx
It all depends on how accurate you need to be. If it is ledger data, then very accurate. If it is forecast data, may be less accurate.
I suggest using RCSI instead of the default READ COMMITTED to get a better point in time count. This is using the SELECT COUNT(*) FROM [TABLE] syntax.
http://www.sqlpass.org/summit/2013/Sessions/SessionDetails.aspx?sid=4730
Randy Knight had a great presentation on this last year.
You can also look at my isolation presentation that has code that demonstrates that READ COMMITTED can be inaccurate.
http://craftydba.com/?page_id=880
Listed below are three solutions.
Good luck
J
-- Show time & i/o
SET STATISTICS TIME ON
SET STATISTICS IO ON
GO
-- Remove clean buffers & clear plan cache
CHECKPOINT
DBCC DROPCLEANBUFFERS
DBCC FREEPROCCACHE
GO
-- test database
use adventureworks2012
go
-- traverse the table
select count(*) as 'rows' from person.address
go
/*
SQL Server parse and compile time: CPU time = 0 ms, elapsed time = 0 ms.
(1 row(s) affected) Table 'Address'. Scan count 1, logical reads 36, physical reads 1, read-ahead reads 34, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0.
SQL Server Execution Times: CPU time = 15 ms, elapsed time = 26 ms.
*/
-- Look at sysindexes
select o.name as 'Table', max(i.rows) 'Rows'
from sysobjects o join sysindexes i
on o.id = i.id
where
(i.indid = 1 or i.indid = 0) and
o.type = 'U' and
o.name = 'Address'
group by o.name
go
/*
SQL Server parse and compile time: CPU time = 15 ms, elapsed time = 132 ms.
(1 row(s) affected) Table 'sysidxstats'. Scan count 1, logical reads 2, physical reads 2, read-ahead reads 0, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0. Table 'sysschobjs'. Scan count 1, logical reads 6, physical reads 3, read-ahead reads 0, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0.
SQL Server Execution Times: CPU time = 0 ms, elapsed time = 36 ms.
*/
-- Look at sys.partitions
SELECT max(rows) as 'Rows' FROM sys.partitions
WHERE object_id = object_id('Person.Address');
/*
SQL Server parse and compile time: CPU time = 16 ms, elapsed time = 104 ms.
(1 row(s) affected) Table 'Worktable'. Scan count 0, logical reads 0, physical reads 0, read-ahead reads 0, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0. Table 'sysidxstats'. Scan count 1, logical reads 10, physical reads 2, read-ahead reads 0, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0. Table 'sysschobjs'. Scan count 0, logical reads 4, physical reads 2, read-ahead reads 0, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0. Table 'sysrowsets'. Scan count 1, logical reads 6, physical reads 1, read-ahead reads 24, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0.
SQL Server Execution Times: CPU time = 0 ms, elapsed time = 34 ms.
*/
It is because sqlsrv_query()
uses SQLSRV_CURSOR_FORWARD
cursor type by default. However, in order to get a result from sqlsrv_num_rows()
, you should choose one of these cursor types below:
For more information, check: Cursor Types (SQLSRV Driver)
In conclusion, if you use your query like:
$query = sqlsrv_query($conn, $result, array(), array( "Scrollable" => 'static' ));
you will get result in:
$row_count = sqlsrv_num_rows($query);