Allan Bowe
Allan Bowe

Reputation: 12701

Derive unique libref and/or fileref in SAS

I often need to assign (and de-assign) temporary librefs/filerefs as part of utility macros - and thus I need to avoid naming conflicts with any existing librefs/filerefs. I know I could query the sashelp or dictionary tables and use conditional logic to iterate until I find one that isn't assigned, but I wondered if there was some easier way?

For instance, the following will create a uniquely named dataset in the work library:

data;run;

Is there some equivalent for librefs / filerefs?

Upvotes: 1

Views: 270

Answers (4)

Allan Bowe
Allan Bowe

Reputation: 12701

actually writing one was fairly trivial, and didn't involve querying the (expensive) dictionary table:

libname mcore0 (work);
libname mcore1 (work);
libname mcore2 (work);

%macro mf_getuniquelibref(prefix=mcore,maxtries=1000);
%local x;
%let x=0;
%do x=0 %to &maxtries;
 %if %sysfunc(libref(&prefix&x)) ne 0 %then %do;
    %put Libref &prefix&x is available!;
    &prefix&x
    %return;
 %end;
%end;
%put unable to find available libref in range &prefix.0-&maxtries;
%mend;

%let libref=%mf_getuniquelibref();
%put &=libref;

which returns;

enter image description here

UPDATE:

I've added macros for both of these to the MacroCore library and they can be utilised as follows:

filename mc url "https://raw.githubusercontent.com/sasjs/core/main/macrocore.sas";
%inc mc;

%let libref=%mf_getuniquelibref();
%let fileref=%mf_getuniquefileref();

Upvotes: 1

data _null_
data _null_

Reputation: 9109

The LIBNAME function has a similar feature as FILENAME but it does not populate the reference name variable as with FILENAME. The only way I can think of would be to compare SASHELP.VLIBNAM before and after. The librefs are in the form WC00000n.

79   data _null_;
80      length libref $32.;
81      libref = ' ';
82      rc = libname(libref,'.');
83      msg = sysmsg();
84      put _all_;
85      run;

libref=  rc=-70004 msg=NOTE: Libref  refers to the same physical library as WC000004. _ERROR_=0 _N_=1

Upvotes: 1

Richard
Richard

Reputation: 27526

The undocumented monotonic function, invoked in the open execution space, is very handy for obtaining an unused value.

libname mylib "C:\temp\sandbox";

data mylib.data%sysfunc(monotonic());
  … 
run;

Or code a macro to deliver a name for a libref. The macro can also check for existence if so desired:

%macro nextName(lib=,base=data,check=1);
  %local index name;
  %if %length(&lib) %then %let lib=&lib..;/* handle non-empty lib */
  %do %until (&check and not %sysfunc(exist(&name,data)));
    %let name = &lib.&base.%sysfunc(monotonic());
  %end;
  &name
%mend;

data data3;run;
data data4;run;

%put %nextName();
%put %nextName();
%put %nextName();
%put %nextName();

proc sort data=sashelp.class out=%nextname();
  by age;
run;

You could go robust macro implementation and test for lib existence and valid check value.

Upvotes: 1

Tom
Tom

Reputation: 51621

The FILENAME() function already provides a method for this. When you call it with a missing value for the fileref it generates one using format #LNnnnnn.

6     data test;
7       length fileref $8 ;
8       rc=filename(fileref,,'temp');
9       put rc= fileref=;
10    run;

rc=0 fileref=#LN00056
NOTE: The data set WORK.TEST has 1 observations and 2 variables.
NOTE: DATA statement used (Total process time):
      real time           0.02 seconds
      cpu time            0.01 seconds


11    %global fileref ;
12    %let rc=%sysfunc(filename(fileref,,temp));
13    %put &=rc &=fileref ;
RC=0 FILEREF=#LN00058

Upvotes: 2

Related Questions