BookmarkSubscribeRSS Feed

Determining the number of observations in a SAS data set efficiently

Started ‎07-03-2018 by
Modified ‎09-12-2018 by
Views 102,947

SAS data sets consist of a descriptor portion and a data portion that contains the data values. The descriptor portion of a SAS data set contains detailed information about the data set. This information includes:

  • The name of the data set and its member type
  • The date and time the data set was created
  • The number of observations
  • The number of variables
  • The engine type

Reading the descriptor portion is one of the most efficient and quickest ways of determining the number of observations in a SAS data set.  Here are some examples:


/* SAS V9.x and higher */
data _NULL_;
	if 0 then set sashelp.class nobs=n;
	call symputx('nrows',n);
%put nobs=&nrows;
  • The "if 0" is a a conditional statement designed to never be executed at run-time and works since the "set sashelp.class" gives the header information of the data set class to the compiler which sets up the PDV accordingly, but is skipped in the execution time because the if condition is false.
  • nobs is a SAS automatic variable which contains the number of records in the data set named in the set statement. The code, nobs = n, places the value of nobs (the number of records in the sashelp.class dataset) in the variable n.
  • The STOP statement is used to prevent an endless loop because EOF is never reached.

Checking for empty data set

Many times users don't need to know how many obs there are, just whether there are any. In such cases, a data step like the following might be just what is needed. This technique also has the advantage that it works for views and other data sets where the number of observations is not available in the data set header (Don Henderson's tip from


data _null_;
 call symput('AnyObs','0'); /* set to 0 for No */
 set &data(obs=1);
 call symput('AnyObs','1'); /* if got here there are obs so set to 1 for Yes */


Access the descriptor information in SAS macro

The metadata can also be accessed by the macro language using DATA step functions. The ATTRN function is used with the NLOBS argument in the %OBSCNT macro shown below to retrieve the number of non-deleted observations from the meta data.


%macro obscnt(dsn);
%local nobs dsnid;
%let nobs=.;
%* Open the data set of interest;
%let dsnid = %sysfunc(open(&dsn));
%* If the open was successful get the;
%* number of observations and CLOSE &dsn;
%if &dsnid %then %do;
     %let nobs=%sysfunc(attrn(&dsnid,nlobs));
     %let rc  =%sysfunc(close(&dsnid));
%else %do;
     %put Unable to open &dsn - %sysfunc(sysmsg());
%* Return the number of observations;
%mend obscnt;


Using DICTIONARY tables and PROC SQL

SAS dictionary tables can also be used to load the number of observations into a macro variable:


proc sql noprint;
	select nobs into :nobs separated by ' ' from dictionary.tables
	where libname='SASHELP' and memname='CLASS';
%put TNote:  nobs=&nobs;


Thanks to Alberto Negron and Tom Robinson for posting this help on!


It depends on the engine . If you have SPDS ,you can't get nobs by your code.

Then @Ksharp let me tell you and others that for SPDS tables you can find this information in dictionary.tables when performing an explicit pass through.

I wonder if the proc contents wouldn't be faster than dictionary tables (including SPDE) ?



libname X SPDE "E:\SAS_WORK_5400\SPDE";

data X.class;
  do _N_ = 1 to 1e6;
    do POINT = 1 to NOBS;
      set sashelp.class NOBS=NOBS POINT=POINT;

proc contents noprint
  data = x.class
  OUT = OUT(keep=nobs)
data _NULL_;
	set OUT(obs=1);
	call symputx('nrows',nobs);

%put &=nrows;

In the Checking for empty data set code, won't the first call symput run for every iteration of the data step, but the second one will fail to run on the last iteration of the data step?  So won't the value of the AnyObs macro variable always be set to '0', regardless of the number of observations read?  Looking at the log after running the code below seems to confirm this.


data _null_;
    put _N_;
    put "A";
    call symput('AnyObs','0'); 
    put "B"; /* this will always be the last thing written to the log */
    set &data(obs=1);
    put "C";
    call symput('AnyObs','1'); 
    put "D";


Version history
Last update:
‎09-12-2018 08:40 AM
Updated by:



Registration is open! SAS is returning to Vegas for an AI and analytics experience like no other! Whether you're an executive, manager, end user or SAS partner, SAS Innovate is designed for everyone on your team. Register for just $495 by 12/31/2023.

If you are interested in speaking, there is still time to submit a session idea. More details are posted on the website. 

Register now!

Free course: Data Literacy Essentials

Data Literacy is for all, even absolute beginners. Jump on board with this free e-learning  and boost your career prospects.

Get Started

Article Labels
Article Tags