<?xml version="1.0" encoding="UTF-8"?>
<rss xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" xmlns:taxo="http://purl.org/rss/1.0/modules/taxonomy/" version="2.0">
  <channel>
    <title>topic Re: how to delete sas dataset created during certain macro run ? in SAS Programming</title>
    <link>https://communities.sas.com/t5/SAS-Programming/how-to-delete-sas-dataset-created-during-certain-macro-run/m-p/788337#M252029</link>
    <description>&lt;P&gt;&lt;a href="https://communities.sas.com/t5/user/viewprofilepage/user-id/19879"&gt;@Quentin&lt;/a&gt;&amp;nbsp;,&lt;/P&gt;
&lt;P&gt;I think that the functionality of "local macro library" can be achieved with help of MD5(footnote1). From what I've got on the fly (using &lt;a href="https://communities.sas.com/t5/user/viewprofilepage/user-id/4"&gt;@ChrisHemedinger&lt;/a&gt;&amp;nbsp;idea with the USER library) is the following:&amp;nbsp;&lt;/P&gt;
&lt;P&gt;0) set this at the begging of the code:&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;PRE&gt;&lt;CODE class=" language-sas"&gt;options dlcreatedir;
%let lib = WORK;&lt;/CODE&gt;&lt;/PRE&gt;
&lt;P&gt;to allow create sub-directories inside the WORK directory, and create global macro variable LIB.&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;1) you need this little macro, for convenience:&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;PRE&gt;&lt;CODE class=" language-sas"&gt;%macro library(in);
_%sysfunc(MD5(%upcase(&amp;amp;in.)),hex7.)
%mend library;&lt;/CODE&gt;&lt;/PRE&gt;
&lt;P&gt;to ensure 8 character long library names (macro name can be longer than 8, so we need to get some handy "shortcut".&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;Now:&lt;/P&gt;
&lt;P&gt;2) add this "prefix"(header) to your macro code:&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;PRE&gt;&lt;CODE class=" language-sas"&gt;/* get external lib */
%local outlib;
%let outlib = &amp;amp;lib.;
/* set local user */
%local lib macroName;
%let macroName = &amp;amp;sysmacroname.; /* FOOTNOTE */
%let lib = %library(&amp;amp;macroName.);
libname &amp;amp;lib. "%sysfunc(pathname(work))/&amp;amp;lib.";
options user = &amp;amp;lib.;&lt;/CODE&gt;&lt;/PRE&gt;
&lt;P&gt;3) and the following "suffix"(footer)&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;PRE&gt;&lt;CODE class=" language-sas"&gt;options user = &amp;amp;outlib.;&lt;/CODE&gt;&lt;/PRE&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;so the structure of the macro would be something like:&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;PRE&gt;&lt;CODE class=" language-sas"&gt;%macro myMacro(some,parameters);
/* header */
/* get external lib */
%local outlib;
%let outlib = &amp;amp;lib.;
/* set local user */
%local lib macroName;
%let macroName = &amp;amp;sysmacroname.;
%let lib = %library(&amp;amp;macroName.);
libname &amp;amp;lib. "%sysfunc(pathname(work))/&amp;amp;lib.";
options user = &amp;amp;lib.;

/**/
  /* your macro code goes here */
/**/

/* footer */
options user = &amp;amp;outlib.;
%mend myMacro;&lt;/CODE&gt;&lt;/PRE&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;&lt;SPAN style="font-family: inherit;"&gt;Whenever you create a "libnameles" data set in such a macro, it will be stored in that "local" library generated for that particular macro. And Thanks to the %library() macro you can easy get the library for a given macro (see next example).&lt;/SPAN&gt;&lt;/P&gt;
&lt;P&gt;&lt;SPAN style="font-family: inherit;"&gt;The:&lt;/SPAN&gt;&lt;/P&gt;
&lt;P&gt;&lt;SPAN style="font-family: inherit;"&gt;&lt;CODE class=" language-sas"&gt;%let macroName = &amp;amp;sysmacroname.;&lt;/CODE&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P&gt;&lt;SPAN style="font-family: inherit;"&gt;part is needed because call of the form:&lt;/SPAN&gt;&lt;/P&gt;
&lt;P&gt;&lt;SPAN style="font-family: inherit;"&gt;&lt;CODE class=" language-sas"&gt;%library(&amp;amp;sysMacroName.);&lt;/CODE&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P&gt;&lt;SPAN style="font-family: inherit;"&gt;resolves the sysMacroName macro variable to "library" (footnote example).&lt;/SPAN&gt;&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;&lt;SPAN style="font-family: inherit;"&gt;Bigger example would be:&lt;/SPAN&gt;&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;PRE&gt;&lt;CODE class=" language-sas"&gt;options dlcreatedir;
%let lib = WORK;

%macro library(in);
_%sysfunc(MD5(%upcase(&amp;amp;in.)),hex7.)
%mend library;


%macro b_short(id);
/* get external lib */
%local outlib;
%let outlib = &amp;amp;lib.;
/* set local user */
%local lib macroName;
%let macroName = &amp;amp;sysmacroname.;
%let lib = %library(&amp;amp;macroName.);
libname &amp;amp;lib. "%sysfunc(pathname(work))/&amp;amp;lib.";
options user = &amp;amp;lib.;

/**/
  /* your macro code goes here */
  data dataset_B_&amp;amp;id.; /* that one goes to the "local" library */
    set sashelp.class;
  run;
/**/

options user = &amp;amp;outlib.;
%mend b_short;



%macro c_very_very_long(id);
/* header */
/* get external lib */
%local outlib;
%let outlib = &amp;amp;lib.;
/* set local user */
%local lib macroName;
%let macroName = &amp;amp;sysmacroname.;
%let lib = %library(&amp;amp;macroName.);
libname &amp;amp;lib. "%sysfunc(pathname(work))/&amp;amp;lib.";
options user = &amp;amp;lib.;

/**/
  /* your macro code goes here */
  %b_short(1);
  
  data dataset_C_&amp;amp;id.; /* that one goes to the "local" library */
    set sashelp.class;
  run;

  %b_short(3);


  data %library(b_short).dataset_C_&amp;amp;id.; /* that one goes to the "external" library */
    set sashelp.class;
  run;

/**/

/* footer */
options user = &amp;amp;outlib.;
%mend c_very_very_long;


options mprint mlogic;

%c_very_very_long(2)&lt;/CODE&gt;&lt;/PRE&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;All the best&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;Bart&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;Footnote 1: Wont work with 9.4M5 since M5 has a bug which doesn't allow to use MD5() in %sysfunc()&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;Footnote example, in open code:&lt;/P&gt;
&lt;PRE&gt;&lt;CODE class=" language-sas"&gt;%macro test(x);
%put *&amp;amp;=x.*;
%mend;

%put #&amp;amp;=sysmacroname.#;
%test(&amp;amp;sysmacroname.)&lt;/CODE&gt;&lt;/PRE&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;</description>
    <pubDate>Tue, 04 Jan 2022 19:58:19 GMT</pubDate>
    <dc:creator>yabwon</dc:creator>
    <dc:date>2022-01-04T19:58:19Z</dc:date>
    <item>
      <title>how to delete sas dataset created during certain macro run ?</title>
      <link>https://communities.sas.com/t5/SAS-Programming/how-to-delete-sas-dataset-created-during-certain-macro-run/m-p/788094#M251904</link>
      <description>&lt;P&gt;is there any way to delete all sas dataset created only while executing some macro ?&lt;/P&gt;</description>
      <pubDate>Mon, 03 Jan 2022 14:20:53 GMT</pubDate>
      <guid>https://communities.sas.com/t5/SAS-Programming/how-to-delete-sas-dataset-created-during-certain-macro-run/m-p/788094#M251904</guid>
      <dc:creator>abhinayingole</dc:creator>
      <dc:date>2022-01-03T14:20:53Z</dc:date>
    </item>
    <item>
      <title>Re: how to delete sas dataset created during certain macro run ?</title>
      <link>https://communities.sas.com/t5/SAS-Programming/how-to-delete-sas-dataset-created-during-certain-macro-run/m-p/788098#M251907</link>
      <description>&lt;P&gt;The best way to do this, if you can, is to direct all of the data sets to a temp libname while the macro runs. If the macro allows you to specify the output location, use this temp library as the destination. Use PROC DATASETS to delete its contents when finished, or wait until the SAS session ends and it will be cleaned up because it's a temporary library in the WORK folder. You can also redirect one-level names from the default of WORK to the temp library by using OPTIONS USER=;&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;LI-CODE lang="sas"&gt;%let outdir=%sysfunc(getoption(work));
/* create a results folder in the WORK area */
options dlcreatedir;
libname RES "&amp;amp;outdir./results" access=temp;

/* optionally redirect one-level names from WORK to RES */
options user=RES;

/* run macro and direct output to RES library */
%myMacro(lib=RES);

options user=WORK;

proc datasets lib=RES kill nodetails nolist; quit;
libname RES CLEAR;&lt;/LI-CODE&gt;
&lt;P&gt;&amp;nbsp;This will also "hide" the generated data sets from client apps that detect them and show/open them automatically, like SAS Enterprise Guide.&lt;/P&gt;</description>
      <pubDate>Mon, 03 Jan 2022 14:39:34 GMT</pubDate>
      <guid>https://communities.sas.com/t5/SAS-Programming/how-to-delete-sas-dataset-created-during-certain-macro-run/m-p/788098#M251907</guid>
      <dc:creator>ChrisHemedinger</dc:creator>
      <dc:date>2022-01-03T14:39:34Z</dc:date>
    </item>
    <item>
      <title>Re: how to delete sas dataset created during certain macro run ?</title>
      <link>https://communities.sas.com/t5/SAS-Programming/how-to-delete-sas-dataset-created-during-certain-macro-run/m-p/788099#M251908</link>
      <description>&lt;P&gt;You could give the datasets the same prefix like an underscore `_` followed by some pattern like `_mds` for 'macro data set'.&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;Then it's as simple as:&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;PRE&gt;&lt;CODE class=" language-sas"&gt;proc datasets library = work;
delete _mds:;
run;
quit;&lt;/CODE&gt;&lt;/PRE&gt;
&lt;P&gt;Example:&lt;/P&gt;
&lt;PRE&gt;&lt;CODE class=" language-sas"&gt;proc sql;
	select
				distinct make
					into: makes separated by " "
	from
				sashelp.cars;
quit;

%macro dsmaker ();
%do i = 1 %to %sysfunc(countw(&amp;amp;makes., " "));
%let dsn = %scan(&amp;amp;makes., &amp;amp;i., " ");

proc sql;
	create table 	_mds_&amp;amp;dsn. as
		select
					*
		from
					sashelp.cars
		where
					make = "&amp;amp;dsn.";
quit;

%end;
%mend;

%dsmaker();

proc datasets library = work;
	delete _mds:;
run;
quit;&lt;/CODE&gt;&lt;/PRE&gt;
&lt;P&gt;An error gets thrown because Mercedes-Benz has a hyphen in it. I'm ignoring that since it's just an example.&lt;/P&gt;</description>
      <pubDate>Mon, 03 Jan 2022 14:40:02 GMT</pubDate>
      <guid>https://communities.sas.com/t5/SAS-Programming/how-to-delete-sas-dataset-created-during-certain-macro-run/m-p/788099#M251908</guid>
      <dc:creator>maguiremq</dc:creator>
      <dc:date>2022-01-03T14:40:02Z</dc:date>
    </item>
    <item>
      <title>Re: how to delete sas dataset created during certain macro run ?</title>
      <link>https://communities.sas.com/t5/SAS-Programming/how-to-delete-sas-dataset-created-during-certain-macro-run/m-p/788104#M251910</link>
      <description>&lt;P&gt;Hello&amp;nbsp;&lt;a href="https://communities.sas.com/t5/user/viewprofilepage/user-id/4"&gt;@ChrisHemedinger&lt;/a&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;I have done this a long time ago, but as I recall, once you execute the command&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;PRE&gt;&lt;CODE class=" language-sas"&gt;options user=RES;&lt;/CODE&gt;&lt;/PRE&gt;
&lt;P&gt;then any data sets in the WORK library now have to be referred to with two-level names, e.g. WORK.MYDATA; and so you can't just refer to this data set as MYDATA.&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;Is there a workaround? Or is my memory wrong?&lt;/P&gt;</description>
      <pubDate>Mon, 03 Jan 2022 15:23:35 GMT</pubDate>
      <guid>https://communities.sas.com/t5/SAS-Programming/how-to-delete-sas-dataset-created-during-certain-macro-run/m-p/788104#M251910</guid>
      <dc:creator>PaigeMiller</dc:creator>
      <dc:date>2022-01-03T15:23:35Z</dc:date>
    </item>
    <item>
      <title>Re: how to delete sas dataset created during certain macro run ?</title>
      <link>https://communities.sas.com/t5/SAS-Programming/how-to-delete-sas-dataset-created-during-certain-macro-run/m-p/788110#M251912</link>
      <description>&lt;BLOCKQUOTE&gt;&lt;HR /&gt;&lt;a href="https://communities.sas.com/t5/user/viewprofilepage/user-id/10892"&gt;@PaigeMiller&lt;/a&gt;&amp;nbsp;wrote:&lt;BR /&gt;
&lt;P&gt;Hello&amp;nbsp;&lt;a href="https://communities.sas.com/t5/user/viewprofilepage/user-id/4"&gt;@ChrisHemedinger&lt;/a&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;I have done this a long time ago, but as I recall, once you execute the command&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;PRE&gt;&lt;CODE class=" language-sas"&gt;options user=RES;&lt;/CODE&gt;&lt;/PRE&gt;
&lt;P&gt;then any data sets in the WORK library now have to be referred to with two-level names, e.g. WORK.MYDATA; and so you can't just refer to this data set as MYDATA.&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;Is there a workaround? Or is my memory wrong?&lt;/P&gt;
&lt;HR /&gt;&lt;/BLOCKQUOTE&gt;
&lt;P&gt;There is no work around.&amp;nbsp; If you are planning to use the USER lib functionality then you need to plan for when you should be using one level names and when to use two level names.&amp;nbsp;&amp;nbsp;&lt;/P&gt;</description>
      <pubDate>Mon, 03 Jan 2022 15:40:10 GMT</pubDate>
      <guid>https://communities.sas.com/t5/SAS-Programming/how-to-delete-sas-dataset-created-during-certain-macro-run/m-p/788110#M251912</guid>
      <dc:creator>Tom</dc:creator>
      <dc:date>2022-01-03T15:40:10Z</dc:date>
    </item>
    <item>
      <title>Re: how to delete sas dataset created during certain macro run ?</title>
      <link>https://communities.sas.com/t5/SAS-Programming/how-to-delete-sas-dataset-created-during-certain-macro-run/m-p/788113#M251913</link>
      <description>&lt;BLOCKQUOTE&gt;&lt;HR /&gt;&lt;a href="https://communities.sas.com/t5/user/viewprofilepage/user-id/159"&gt;@Tom&lt;/a&gt;&amp;nbsp;wrote:&lt;BR /&gt;
&lt;BLOCKQUOTE&gt;&lt;HR /&gt;&lt;a href="https://communities.sas.com/t5/user/viewprofilepage/user-id/10892"&gt;@PaigeMiller&lt;/a&gt;&amp;nbsp;wrote:&lt;BR /&gt;
&lt;P&gt;Hello&amp;nbsp;&lt;a href="https://communities.sas.com/t5/user/viewprofilepage/user-id/4"&gt;@ChrisHemedinger&lt;/a&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;I have done this a long time ago, but as I recall, once you execute the command&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;PRE&gt;&lt;CODE class=" language-sas"&gt;options user=RES;&lt;/CODE&gt;&lt;/PRE&gt;
&lt;P&gt;then any data sets in the WORK library now have to be referred to with two-level names, e.g. WORK.MYDATA; and so you can't just refer to this data set as MYDATA.&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;Is there a workaround? Or is my memory wrong?&lt;/P&gt;
&lt;HR /&gt;&lt;/BLOCKQUOTE&gt;
&lt;P&gt;There is no work around.&amp;nbsp; If you are planning to use the USER lib functionality then you need to plan for when you should be using one level names and when to use two level names.&amp;nbsp;&amp;nbsp;&lt;/P&gt;
&lt;HR /&gt;&lt;/BLOCKQUOTE&gt;
&lt;P&gt;That was my conclusion too.&lt;/P&gt;</description>
      <pubDate>Mon, 03 Jan 2022 15:47:26 GMT</pubDate>
      <guid>https://communities.sas.com/t5/SAS-Programming/how-to-delete-sas-dataset-created-during-certain-macro-run/m-p/788113#M251913</guid>
      <dc:creator>PaigeMiller</dc:creator>
      <dc:date>2022-01-03T15:47:26Z</dc:date>
    </item>
    <item>
      <title>Re: how to delete sas dataset created during certain macro run ?</title>
      <link>https://communities.sas.com/t5/SAS-Programming/how-to-delete-sas-dataset-created-during-certain-macro-run/m-p/788156#M251935</link>
      <description>&lt;P&gt;Another approach would be get a data set of the datasets in the Work library prior to the macro run, again after the run (or possibly better as the last step of the macro), compare the two to create a delete list then delete them. However this may not be desired if you actually intentionally also create wanted output sets in the Work library, which is not clear from your description if that may be the case or not.&lt;/P&gt;</description>
      <pubDate>Mon, 03 Jan 2022 17:35:02 GMT</pubDate>
      <guid>https://communities.sas.com/t5/SAS-Programming/how-to-delete-sas-dataset-created-during-certain-macro-run/m-p/788156#M251935</guid>
      <dc:creator>ballardw</dc:creator>
      <dc:date>2022-01-03T17:35:02Z</dc:date>
    </item>
    <item>
      <title>Re: how to delete sas dataset created during certain macro run ?</title>
      <link>https://communities.sas.com/t5/SAS-Programming/how-to-delete-sas-dataset-created-during-certain-macro-run/m-p/788271#M251997</link>
      <description>Thanks &lt;a href="https://communities.sas.com/t5/user/viewprofilepage/user-id/13884"&gt;@ballardw&lt;/a&gt; -- I agree with you completely. Since we had limited information from the OP, I decided to make some contrived example that had a set of assumptions that I didn't address. If they provided us more information, I probably would not have gone this route.</description>
      <pubDate>Tue, 04 Jan 2022 13:45:33 GMT</pubDate>
      <guid>https://communities.sas.com/t5/SAS-Programming/how-to-delete-sas-dataset-created-during-certain-macro-run/m-p/788271#M251997</guid>
      <dc:creator>maguiremq</dc:creator>
      <dc:date>2022-01-04T13:45:33Z</dc:date>
    </item>
    <item>
      <title>Re: how to delete sas dataset created during certain macro run ?</title>
      <link>https://communities.sas.com/t5/SAS-Programming/how-to-delete-sas-dataset-created-during-certain-macro-run/m-p/788306#M252017</link>
      <description>&lt;P&gt;Very interesting solution,&amp;nbsp;&lt;a href="https://communities.sas.com/t5/user/viewprofilepage/user-id/4"&gt;@ChrisHemedinger&lt;/a&gt;&amp;nbsp;, thanks.&amp;nbsp; I had never even noticed access=temp option.&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;I'm curious, if we change the question to a macro design question (hijacking the thread a bit), what others would think of using this USER= approach as a way to create a namespace for temporary datasets created by a macro.&amp;nbsp; Typically for utility macros I've used underscore prefixes or similar on dataset names when creating temp datasets inside a macro, and deleted them at the end.&amp;nbsp; But I hadn't thought about using the USER= option to redirect one level names to a dedicated directory and then KILLing it at the end.&amp;nbsp; I guess for this approach to work each macro would need a unique name for its user library.&amp;nbsp; Because when an OUTER macro calls an INNER macro, INNER would need an independent user library, and it would also need to be able to save and restore the value of OUTER user library.&amp;nbsp; But that doesn't seem like it would be hard.&amp;nbsp;&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;If INNER was passed a one-level name for an input dataset, it would also need a rule to determine which outer users libraries should be searched. Meaning, it should probably look in the user library of OUTER first to see if it exists, and then look in the session work library.&amp;nbsp; That could be a hassle to implement when you have multiple levels of nested macro calls, you would have (conceptually) nested user libraries.&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;But it seems like an appealing idea, to know that any one-level name datasets created by a macro are automatically written a dedicated namespace.&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;Any thoughts,&amp;nbsp;&lt;a href="https://communities.sas.com/t5/user/viewprofilepage/user-id/159"&gt;@Tom&lt;/a&gt;&amp;nbsp;&lt;a href="https://communities.sas.com/t5/user/viewprofilepage/user-id/10892"&gt;@PaigeMiller&lt;/a&gt;&amp;nbsp;&lt;a href="https://communities.sas.com/t5/user/viewprofilepage/user-id/4954"&gt;@Astounding&lt;/a&gt;&amp;nbsp;&lt;a href="https://communities.sas.com/t5/user/viewprofilepage/user-id/35763"&gt;@yabwon&lt;/a&gt;&amp;nbsp;?&lt;/P&gt;</description>
      <pubDate>Tue, 04 Jan 2022 16:15:25 GMT</pubDate>
      <guid>https://communities.sas.com/t5/SAS-Programming/how-to-delete-sas-dataset-created-during-certain-macro-run/m-p/788306#M252017</guid>
      <dc:creator>Quentin</dc:creator>
      <dc:date>2022-01-04T16:15:25Z</dc:date>
    </item>
    <item>
      <title>Re: how to delete sas dataset created during certain macro run ?</title>
      <link>https://communities.sas.com/t5/SAS-Programming/how-to-delete-sas-dataset-created-during-certain-macro-run/m-p/788307#M252018</link>
      <description>&lt;P&gt;I would like to see this in a separate thread.&lt;/P&gt;</description>
      <pubDate>Tue, 04 Jan 2022 16:18:50 GMT</pubDate>
      <guid>https://communities.sas.com/t5/SAS-Programming/how-to-delete-sas-dataset-created-during-certain-macro-run/m-p/788307#M252018</guid>
      <dc:creator>PaigeMiller</dc:creator>
      <dc:date>2022-01-04T16:18:50Z</dc:date>
    </item>
    <item>
      <title>Re: how to delete sas dataset created during certain macro run ?</title>
      <link>https://communities.sas.com/t5/SAS-Programming/how-to-delete-sas-dataset-created-during-certain-macro-run/m-p/788319#M252022</link>
      <description>&lt;P&gt;&lt;a href="https://communities.sas.com/t5/user/viewprofilepage/user-id/19879"&gt;@Quentin&lt;/a&gt;&amp;nbsp;,&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;Just a few related thoughts ...&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;You bring up legitimate cautions about what could happen when each macro has its own value for USER=.&amp;nbsp; One more that you hadn't mentioned:&amp;nbsp; What if an inner macro uses the same USER= library as an outer macro?&amp;nbsp; The outer macro's data sets would likely be erased (perhaps accidentally).&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;For a few reasons, I prefer to avoid this technique (but I have used it).&amp;nbsp; Here are some alternatives to consider.&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;Before running a macro, capture a snapshot of dictionary.tables.&amp;nbsp; When the macro ends, again capture a snapshot and compare it to the original snapshot.&amp;nbsp; Delete any additions.&amp;nbsp; Notice that this does not necessary limit the processing to the WORK library (which might be a blessing or a curse).&amp;nbsp; Technically, the original post doesn't limit the deletions to temporary data sets although that might very well have been the intention.&amp;nbsp;&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;Instead of creating a zillion temporary data sets, create just one and reuse a single name.&amp;nbsp; Modify the macro structure to then (if appropriate) append results in this one name to a larger, master output data set.&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;Or, delete data sets inside the macro once they are no longer needed.&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;I don't like to burden the user with obligations that put the data in a perilous position.&amp;nbsp; If the user has to ask this question in the first place, I would be hesitant to give the user the power to specify values for multiple USER= options.&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;Anyway, food for thought.&lt;/P&gt;</description>
      <pubDate>Tue, 04 Jan 2022 18:06:34 GMT</pubDate>
      <guid>https://communities.sas.com/t5/SAS-Programming/how-to-delete-sas-dataset-created-during-certain-macro-run/m-p/788319#M252022</guid>
      <dc:creator>Astounding</dc:creator>
      <dc:date>2022-01-04T18:06:34Z</dc:date>
    </item>
    <item>
      <title>Re: how to delete sas dataset created during certain macro run ?</title>
      <link>https://communities.sas.com/t5/SAS-Programming/how-to-delete-sas-dataset-created-during-certain-macro-run/m-p/788337#M252029</link>
      <description>&lt;P&gt;&lt;a href="https://communities.sas.com/t5/user/viewprofilepage/user-id/19879"&gt;@Quentin&lt;/a&gt;&amp;nbsp;,&lt;/P&gt;
&lt;P&gt;I think that the functionality of "local macro library" can be achieved with help of MD5(footnote1). From what I've got on the fly (using &lt;a href="https://communities.sas.com/t5/user/viewprofilepage/user-id/4"&gt;@ChrisHemedinger&lt;/a&gt;&amp;nbsp;idea with the USER library) is the following:&amp;nbsp;&lt;/P&gt;
&lt;P&gt;0) set this at the begging of the code:&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;PRE&gt;&lt;CODE class=" language-sas"&gt;options dlcreatedir;
%let lib = WORK;&lt;/CODE&gt;&lt;/PRE&gt;
&lt;P&gt;to allow create sub-directories inside the WORK directory, and create global macro variable LIB.&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;1) you need this little macro, for convenience:&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;PRE&gt;&lt;CODE class=" language-sas"&gt;%macro library(in);
_%sysfunc(MD5(%upcase(&amp;amp;in.)),hex7.)
%mend library;&lt;/CODE&gt;&lt;/PRE&gt;
&lt;P&gt;to ensure 8 character long library names (macro name can be longer than 8, so we need to get some handy "shortcut".&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;Now:&lt;/P&gt;
&lt;P&gt;2) add this "prefix"(header) to your macro code:&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;PRE&gt;&lt;CODE class=" language-sas"&gt;/* get external lib */
%local outlib;
%let outlib = &amp;amp;lib.;
/* set local user */
%local lib macroName;
%let macroName = &amp;amp;sysmacroname.; /* FOOTNOTE */
%let lib = %library(&amp;amp;macroName.);
libname &amp;amp;lib. "%sysfunc(pathname(work))/&amp;amp;lib.";
options user = &amp;amp;lib.;&lt;/CODE&gt;&lt;/PRE&gt;
&lt;P&gt;3) and the following "suffix"(footer)&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;PRE&gt;&lt;CODE class=" language-sas"&gt;options user = &amp;amp;outlib.;&lt;/CODE&gt;&lt;/PRE&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;so the structure of the macro would be something like:&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;PRE&gt;&lt;CODE class=" language-sas"&gt;%macro myMacro(some,parameters);
/* header */
/* get external lib */
%local outlib;
%let outlib = &amp;amp;lib.;
/* set local user */
%local lib macroName;
%let macroName = &amp;amp;sysmacroname.;
%let lib = %library(&amp;amp;macroName.);
libname &amp;amp;lib. "%sysfunc(pathname(work))/&amp;amp;lib.";
options user = &amp;amp;lib.;

/**/
  /* your macro code goes here */
/**/

/* footer */
options user = &amp;amp;outlib.;
%mend myMacro;&lt;/CODE&gt;&lt;/PRE&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;&lt;SPAN style="font-family: inherit;"&gt;Whenever you create a "libnameles" data set in such a macro, it will be stored in that "local" library generated for that particular macro. And Thanks to the %library() macro you can easy get the library for a given macro (see next example).&lt;/SPAN&gt;&lt;/P&gt;
&lt;P&gt;&lt;SPAN style="font-family: inherit;"&gt;The:&lt;/SPAN&gt;&lt;/P&gt;
&lt;P&gt;&lt;SPAN style="font-family: inherit;"&gt;&lt;CODE class=" language-sas"&gt;%let macroName = &amp;amp;sysmacroname.;&lt;/CODE&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P&gt;&lt;SPAN style="font-family: inherit;"&gt;part is needed because call of the form:&lt;/SPAN&gt;&lt;/P&gt;
&lt;P&gt;&lt;SPAN style="font-family: inherit;"&gt;&lt;CODE class=" language-sas"&gt;%library(&amp;amp;sysMacroName.);&lt;/CODE&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P&gt;&lt;SPAN style="font-family: inherit;"&gt;resolves the sysMacroName macro variable to "library" (footnote example).&lt;/SPAN&gt;&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;&lt;SPAN style="font-family: inherit;"&gt;Bigger example would be:&lt;/SPAN&gt;&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;PRE&gt;&lt;CODE class=" language-sas"&gt;options dlcreatedir;
%let lib = WORK;

%macro library(in);
_%sysfunc(MD5(%upcase(&amp;amp;in.)),hex7.)
%mend library;


%macro b_short(id);
/* get external lib */
%local outlib;
%let outlib = &amp;amp;lib.;
/* set local user */
%local lib macroName;
%let macroName = &amp;amp;sysmacroname.;
%let lib = %library(&amp;amp;macroName.);
libname &amp;amp;lib. "%sysfunc(pathname(work))/&amp;amp;lib.";
options user = &amp;amp;lib.;

/**/
  /* your macro code goes here */
  data dataset_B_&amp;amp;id.; /* that one goes to the "local" library */
    set sashelp.class;
  run;
/**/

options user = &amp;amp;outlib.;
%mend b_short;



%macro c_very_very_long(id);
/* header */
/* get external lib */
%local outlib;
%let outlib = &amp;amp;lib.;
/* set local user */
%local lib macroName;
%let macroName = &amp;amp;sysmacroname.;
%let lib = %library(&amp;amp;macroName.);
libname &amp;amp;lib. "%sysfunc(pathname(work))/&amp;amp;lib.";
options user = &amp;amp;lib.;

/**/
  /* your macro code goes here */
  %b_short(1);
  
  data dataset_C_&amp;amp;id.; /* that one goes to the "local" library */
    set sashelp.class;
  run;

  %b_short(3);


  data %library(b_short).dataset_C_&amp;amp;id.; /* that one goes to the "external" library */
    set sashelp.class;
  run;

/**/

/* footer */
options user = &amp;amp;outlib.;
%mend c_very_very_long;


options mprint mlogic;

%c_very_very_long(2)&lt;/CODE&gt;&lt;/PRE&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;All the best&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;Bart&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;Footnote 1: Wont work with 9.4M5 since M5 has a bug which doesn't allow to use MD5() in %sysfunc()&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;Footnote example, in open code:&lt;/P&gt;
&lt;PRE&gt;&lt;CODE class=" language-sas"&gt;%macro test(x);
%put *&amp;amp;=x.*;
%mend;

%put #&amp;amp;=sysmacroname.#;
%test(&amp;amp;sysmacroname.)&lt;/CODE&gt;&lt;/PRE&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;</description>
      <pubDate>Tue, 04 Jan 2022 19:58:19 GMT</pubDate>
      <guid>https://communities.sas.com/t5/SAS-Programming/how-to-delete-sas-dataset-created-during-certain-macro-run/m-p/788337#M252029</guid>
      <dc:creator>yabwon</dc:creator>
      <dc:date>2022-01-04T19:58:19Z</dc:date>
    </item>
    <item>
      <title>Re: how to delete sas dataset created during certain macro run ?</title>
      <link>https://communities.sas.com/t5/SAS-Programming/how-to-delete-sas-dataset-created-during-certain-macro-run/m-p/788362#M252042</link>
      <description>&lt;P&gt;Thanks&amp;nbsp;&lt;a href="https://communities.sas.com/t5/user/viewprofilepage/user-id/35763"&gt;@yabwon&lt;/a&gt;, good stuff.&amp;nbsp; I like the %library macro using MD5.&amp;nbsp; I think you've shown me something like that before... I'm not sure I like the idea of specifying which library a dataset should be written to. I was thinking of the following goals:&lt;/P&gt;
&lt;OL&gt;
&lt;LI&gt;A macro should have its own local user library that will be used for creating and reading datasets with one-level names.&lt;/LI&gt;
&lt;LI&gt;If a macro is passed a one-level dataset name as an argument, it should be interpreted as a reference to a dataset in the calling environment's user library (or WORK library if there is no user library specified in the calling environment).&lt;/LI&gt;
&lt;/OL&gt;
&lt;P&gt;This would not necessarily allow you to reference a dataset from any arbitrary user library, but I think it would meet my primary goal of avoiding name collisions for datasets.&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;If I call (in open code):&lt;/P&gt;
&lt;PRE&gt;&lt;CODE class=" language-sas"&gt;%inner(data=class,out=want)&lt;/CODE&gt;&lt;/PRE&gt;
&lt;P&gt;I want CLASS to be read from the WORK library and WANT to be written to the WORK library, and any "internal" datasets to be written to the user library of inner.&amp;nbsp; Here's my attempt at that macro, using much of the code from you and Chris.&amp;nbsp; I'm not sure I really like my approach here:&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;PRE&gt;&lt;CODE class=" language-sas"&gt;%macro inner(data=,out=) ;

  /*Set up*/
  *calling lib is the libref used for one-level names in the environment that called the macro ;
  *could be WORK or a libref specified in the USER option ;
  %local holduser ;
  %let holduser=%sysfunc(getoption(user)) ;

  %local callinglib ;
  %if &amp;amp;holduser='' or &amp;amp;holduser=WORK %then %do ;
    %let callinglib=WORK ;
  %end ;
  %else %let callinglib=&amp;amp;holduser ;&lt;BR /&gt;&lt;BR /&gt;  *If a dataset name passed in a parameter has only one level, make it a two level name with libref that points to the work/user library of the calling environment ;
  %if %sysfunc(findc(&amp;amp;data,.))=0 %then %let data=&amp;amp;callinglib..&amp;amp;data ;
  %if %sysfunc(findc(&amp;amp;out,.))=0 %then %let out=&amp;amp;callinglib..&amp;amp;out ;


  *create local user library for this macro ;
  %local lib macroName;
  %let macroName = &amp;amp;sysmacroname;
  %let lib = %library(&amp;amp;macroName);
  libname &amp;amp;lib "%sysfunc(pathname(work))/&amp;amp;lib";
  options user = &amp;amp;lib;
&lt;BR /&gt;
  /*main macro code*/
  data step1 ;  * written to local user library ;
    set &amp;amp;data ; * read from work/user library of the calling environment (if one-level name) ;
  run ;
  
  data &amp;amp;out ;   * written to work/user library of the calling environment (if one-level name) ;
    set step1 ; * read from local user library ;
  run ;


  /*cleanup*/
  proc datasets lib=&amp;amp;lib kill nodetails nolist; 
  quit;
  libname &amp;amp;lib CLEAR;
  options user=&amp;amp;holduser ;
%mend inner;&lt;/CODE&gt;&lt;/PRE&gt;
&lt;P&gt;If I have an %OUTER macro which calls %INNER, I want any internal datasets created in OUTER to be written to its user library.&amp;nbsp; And if it passes a one-level dataset name to %INNER, I want %INNER to know that the dataset name is a reference to a dataset in the OUTER user library.&amp;nbsp; So %OUTER looks like below, with 90% of the code is the same setup and cleanup code used in %INNER:&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;PRE&gt;&lt;CODE class=" language-sas"&gt;%macro outer(data=,out=) ;

  /*Set up*/
  *calling lib is the libref used for one-level names in the environment that called the macro ;
  *could be WORK or a libref specified in the USER option ;
  %local holduser ;
  %let holduser=%sysfunc(getoption(user)) ;

  %local callinglib ;
  %if &amp;amp;holduser='' or &amp;amp;holduser=WORK %then %do ;
    %let callinglib=WORK ;
  %end ;
  %else %let callinglib=&amp;amp;holduser ;&lt;BR /&gt;&lt;BR /&gt;  *If a dataset name has only one level, make it a two level name with libref that points to the work/user library of the calling environment ;
  %if %sysfunc(findc(&amp;amp;data,.))=0 %then %let data=&amp;amp;callinglib..&amp;amp;data ;
  %if %sysfunc(findc(&amp;amp;out,.))=0 %then %let out=&amp;amp;callinglib..&amp;amp;out ;

  *create local user library for this macro ;
  %local lib macroName;
  %let macroName = &amp;amp;sysmacroname;
  %let lib = %library(&amp;amp;macroName);
  libname &amp;amp;lib "%sysfunc(pathname(work))/&amp;amp;lib";
  options user = &amp;amp;lib;


  /*main macro code*/
  data stepA ;  * written to local work/user library ;
    set &amp;amp;data ; * read from work/user library of the calling environment (if one-level name) ;
  run ;

  %inner(data=stepA /*read from local work/user libary*/
        ,out=stepB  /*written to local work/user library*/
        )
  
  data &amp;amp;out ;   * written to work/user library of the calling environment (if one-level name) ;
    set stepB ; * read from local work/user library ;
  run ;


  /*cleanup*/
  proc datasets lib=&amp;amp;lib kill nodetails nolist; 
  quit;
  libname &amp;amp;lib CLEAR;
  options user=&amp;amp;holduser ;
%mend outer;
&lt;/CODE&gt;&lt;/PRE&gt;
&lt;P&gt;What I like about this approach is that the main macro code looks normal/readable to me.&amp;nbsp; I'm using one-level names for my temp datasets, and they'll created in a unique local library for each macro, so no collisions (as long as I don't write a recursive macro. : )&amp;nbsp; &amp;nbsp; It also creates a bit of encapsulation.&amp;nbsp; With this setup, a macro cannot read any datasets from the another "scope" (WORK library or another macro's user library), or write any datasets to another scope, unless the one-level dataset names have been passed in as parameter arguments.&amp;nbsp; Other than values passed as parameters, any one level dataset name is seen as reference to a "local" dataset.&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;I don't like the amount of code needed for the setup, but it could be easily abstracted into a helper macro so that wouldn't be much of an issue.&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;A bigger concern is I think it would take me a while to become comfortable reading a log where most of the librefs were MD5 strings rather than human readable.&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;But there's something appealing about giving a macro its own scope to store temporary "local" datasets.&lt;/P&gt;</description>
      <pubDate>Tue, 04 Jan 2022 22:45:22 GMT</pubDate>
      <guid>https://communities.sas.com/t5/SAS-Programming/how-to-delete-sas-dataset-created-during-certain-macro-run/m-p/788362#M252042</guid>
      <dc:creator>Quentin</dc:creator>
      <dc:date>2022-01-04T22:45:22Z</dc:date>
    </item>
    <item>
      <title>Re: how to delete sas dataset created during certain macro run ?</title>
      <link>https://communities.sas.com/t5/SAS-Programming/how-to-delete-sas-dataset-created-during-certain-macro-run/m-p/788402#M252072</link>
      <description>&lt;P&gt;&lt;a href="https://communities.sas.com/t5/user/viewprofilepage/user-id/19879"&gt;@Quentin&lt;/a&gt;&amp;nbsp; few thoughts I have,&lt;/P&gt;
&lt;P&gt;0) I think it is necessary to test stet USER=WORK (or any not null value) at the beginning&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;1) the part:&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;LI-CODE lang="sas"&gt;  %local callinglib ;
  %if &amp;amp;holduser='' or &amp;amp;holduser=WORK %then %do ;
    %let callinglib=WORK ;
  %end ;
  %else %let callinglib=&amp;amp;holduser ;  *If a dataset name passed in a parameter has only one level, make it a two level name with libref that points to the work/user library of the calling environment ;
  %if %sysfunc(findc(&amp;amp;data,.))=0 %then %let data=&amp;amp;callinglib..&amp;amp;data ;
  %if %sysfunc(findc(&amp;amp;out,.))=0 %then %let out=&amp;amp;callinglib..&amp;amp;out ;&lt;/LI-CODE&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;can be simplified to:&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;PRE&gt;&lt;CODE class=" language-sas"&gt;  %let syslast=&amp;amp;data.;
  %let data=&amp;amp;syslast.;

  %let syslast=&amp;amp;out.;
  %let out=&amp;amp;syslast.;&lt;/CODE&gt;&lt;/PRE&gt;
&lt;P&gt;(credit to&amp;nbsp;&lt;a href="https://communities.sas.com/t5/user/viewprofilepage/user-id/12477"&gt;@RichardDeVen&lt;/a&gt;&amp;nbsp;for this trick).&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;3) From my experience I would keep the parameters for "data" and "out" as they are (in particular with properly prepared library assignments) because you could use them not wit one data set but with many, e.g.&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;PRE&gt;&lt;CODE class=" language-sas"&gt;%outer(data=sashelp.class1 sashelp.class2, out=class)&lt;/CODE&gt;&lt;/PRE&gt;
&lt;LI-CODE lang="sas"&gt;%local lib macroName;
  %let macroName = &amp;amp;sysmacroname;
  %let lib = %library(&amp;amp;macroName);
  libname &amp;amp;lib "%sysfunc(pathname(work))/&amp;amp;macroName"; /* &amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt; */
  options user = &amp;amp;lib;&lt;/LI-CODE&gt;
&lt;PRE&gt;&lt;CODE class=" language-sas"&gt;%outer(data=sashelp.class, out=classF(where(sex='F')) classM(where(sex='M')) ) &lt;/CODE&gt;&lt;/PRE&gt;
&lt;P&gt;and with many data sets both approach from 2) gets far more complicated to handle.&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;And in the "inner" macro call could be something like this:&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;PRE&gt;&lt;CODE class=" language-sas"&gt;%inner(data=%library(outer).stepA /*read from local work/user libary*/
       ,out=%library(outer).stepB  /*written to local work/user library*/
      )&lt;/CODE&gt;&lt;/PRE&gt;
&lt;P&gt;or just:&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;PRE&gt;&lt;CODE class=" language-sas"&gt;%inner(data=&amp;amp;lib..stepA /*read from local work/user libary*/
       ,out=&amp;amp;lib..stepB /*written to local work/user library*/
      )&lt;/CODE&gt;&lt;/PRE&gt;
&lt;P&gt;since the lib value is set for that macro (outer).&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;4) To make LOG more "readable" the library macro can be modified a bit:&lt;/P&gt;
&lt;PRE&gt;&lt;CODE class=" language-sas"&gt;%macro library(in);
%put NOTE: Libref for &amp;amp;in. is _%sysfunc(MD5(%upcase(&amp;amp;in.)),hex7.);
_%sysfunc(MD5(%upcase(&amp;amp;in.)),hex7.)
%mend library;&lt;/CODE&gt;&lt;/PRE&gt;
&lt;P&gt;{EDIT} and also in the header it can be set like that:&lt;/P&gt;
&lt;LI-CODE lang="sas"&gt;%local lib macroName;
  %let macroName = &amp;amp;sysmacroname;
  %let lib = %library(&amp;amp;macroName);
  libname &amp;amp;lib "%sysfunc(pathname(work))/&amp;amp;macroName"; /* &amp;lt;&amp;lt;&amp;lt; */
  options user = &amp;amp;lib;&lt;/LI-CODE&gt;
&lt;P&gt;so the directory name is the same as macro name.&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;Bart&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;Full code for with 0), 1), and 2), and 4):&lt;/P&gt;
&lt;PRE&gt;&lt;CODE class=" language-sas"&gt;%macro library(in);
%put NOTE: Libref for &amp;amp;in. is _%sysfunc(MD5(%upcase(&amp;amp;in.)),hex7.);
_%sysfunc(MD5(%upcase(&amp;amp;in.)),hex7.)
%mend library;

options dlcreatedir mprint;
options user=work ;

%macro inner(data=,out=) ;

  /*Set up*/
  *calling lib is the libref used for one-level names in the environment that called the macro ;
  *could be WORK or a libref specified in the USER option ;
  %local holduser ;
  %let holduser=%sysfunc(getoption(user)) ;

  %let syslast=&amp;amp;data.;
  %let data=&amp;amp;syslast.;

  %let syslast=&amp;amp;out.;
  %let out=&amp;amp;syslast.;

  *create local user library for this macro ;
  %local lib macroName;
  %let macroName = &amp;amp;sysmacroname;
  %let lib = %library(&amp;amp;macroName);
  libname &amp;amp;lib "%sysfunc(pathname(work))/&amp;amp;macroName";
  options user = &amp;amp;lib;

  /*main macro code*/
  data step1 ;  * written to local user library ;
    set &amp;amp;data ; * read from work/user library of the calling environment (if one-level name) ;
  run ;
  
  data &amp;amp;out ;   * written to work/user library of the calling environment (if one-level name) ;
    set step1 ; * read from local user library ;
  run ;


  /*cleanup*/
  proc datasets lib=&amp;amp;lib kill nodetails nolist; 
  quit;
  libname &amp;amp;lib CLEAR;
  options user=&amp;amp;holduser ;
%mend inner;

%macro outer(data=,out=) ;

  /*Set up*/
  *calling lib is the libref used for one-level names in the environment that called the macro ;
  *could be WORK or a libref specified in the USER option ;
  %local holduser ;
  %let holduser=%sysfunc(getoption(user)) ;

  %let syslast=&amp;amp;data.;
  %let data=&amp;amp;syslast.;

  %let syslast=&amp;amp;out.;
  %let out=&amp;amp;syslast.;

  *create local user library for this macro ;
  %local lib macroName;
  %let macroName = &amp;amp;sysmacroname;
  %let lib = %library(&amp;amp;macroName);
  libname &amp;amp;lib "%sysfunc(pathname(work))/&amp;amp;macroName";
  options user = &amp;amp;lib;


  /*main macro code*/
  data stepA ;  * written to local work/user library ;
    set &amp;amp;data ; * read from work/user library of the calling environment (if one-level name) ;
  run ;

  %inner(data=&amp;amp;lib..stepA /*read from local work/user libary*/
         ,out=&amp;amp;lib..stepB  /*written to local work/user library*/
        )
  
  data &amp;amp;out ;   * written to work/user library of the calling environment (if one-level name) ;
    set stepB ; * read from local work/user library ;
  run ;


  /*cleanup*/
  proc datasets lib=&amp;amp;lib kill nodetails nolist; 
  quit;
  libname &amp;amp;lib CLEAR;
  options user=&amp;amp;holduser ;
%mend outer;

%outer(data=sashelp.class,out=class_new)&lt;/CODE&gt;&lt;/PRE&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;</description>
      <pubDate>Wed, 05 Jan 2022 07:16:23 GMT</pubDate>
      <guid>https://communities.sas.com/t5/SAS-Programming/how-to-delete-sas-dataset-created-during-certain-macro-run/m-p/788402#M252072</guid>
      <dc:creator>yabwon</dc:creator>
      <dc:date>2022-01-05T07:16:23Z</dc:date>
    </item>
    <item>
      <title>Re: how to delete sas dataset created during certain macro run ?</title>
      <link>https://communities.sas.com/t5/SAS-Programming/how-to-delete-sas-dataset-created-during-certain-macro-run/m-p/788465#M252106</link>
      <description>&lt;P&gt;Wow, thanks Bart.&amp;nbsp; That looks really nice.&amp;nbsp; That trick from Richard is pretty nifty.&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;In that version when you call %inner instead of calling like:&lt;/P&gt;
&lt;PRE&gt;&lt;CODE class=" language-sas"&gt;  %inner(data=&amp;amp;lib..stepA /*read from local work/user library*/
         ,out=&amp;amp;lib..stepB  /*written to local work/user library*/
        )&lt;/CODE&gt;&lt;/PRE&gt;
&lt;P&gt;You could also call like:&lt;/P&gt;
&lt;PRE&gt;&lt;CODE class=" language-sas"&gt;  %inner(data=stepA /*read from local work/user library*/
         ,out=stepB  /*written to local work/user library*/
        )&lt;/CODE&gt;&lt;/PRE&gt;
&lt;P&gt;which I like, because it means that temporary datasets that are "internal" to a macro can always be referenced with one-level names.&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;I would think a lot more about this before doing this in production, but it seems interesting to me.&amp;nbsp;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;Thanks,&lt;/P&gt;
&lt;P&gt;--Q.&lt;/P&gt;</description>
      <pubDate>Wed, 05 Jan 2022 14:36:24 GMT</pubDate>
      <guid>https://communities.sas.com/t5/SAS-Programming/how-to-delete-sas-dataset-created-during-certain-macro-run/m-p/788465#M252106</guid>
      <dc:creator>Quentin</dc:creator>
      <dc:date>2022-01-05T14:36:24Z</dc:date>
    </item>
    <item>
      <title>Re: how to delete sas dataset created during certain macro run ?</title>
      <link>https://communities.sas.com/t5/SAS-Programming/how-to-delete-sas-dataset-created-during-certain-macro-run/m-p/790331#M253018</link>
      <description>&lt;P&gt;If the macro is not creating and deleting librefs you can create a mothering wrapper macro for dispatch of said macro.&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;"&lt;SPAN&gt;Mama's gonna keep baby cosy and warm" - Pink Floyd&lt;/SPAN&gt;&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;Example:&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;PRE&gt;%macro mother (invoke);
  %local time0 time1;
  %put NOTE: Mothering %superq(invoke);
  %let time0 = %sysfunc(datetime());
  %unquote(&amp;amp;invoke)
  %let time1 = %sysfunc(datetime());

  data _null_;
    call execute ('proc sql;');
    do until (last_created);
      set sashelp.vtable end=last_created;
      where memtype = 'DATA' and crdate between &amp;amp;time0 and &amp;amp;time1;
      where also libname not in ('SASHELP', 'MAPS');
      call execute ('drop table ' || cats(libname,'.',memname,';'));
    end;
    call execute ('quit;');
  run;
%mend;

%macro xyzzy ( out=, out2= );
  data &amp;amp;out &amp;amp;out2;
    z=1;
  run;
%mend;

%mother (%nrstr( %xyzzy( out=work.foo, out2=work.snafu ) ));
&lt;/PRE&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;</description>
      <pubDate>Sat, 15 Jan 2022 13:40:47 GMT</pubDate>
      <guid>https://communities.sas.com/t5/SAS-Programming/how-to-delete-sas-dataset-created-during-certain-macro-run/m-p/790331#M253018</guid>
      <dc:creator>RichardDeVen</dc:creator>
      <dc:date>2022-01-15T13:40:47Z</dc:date>
    </item>
  </channel>
</rss>

