<?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: List tables code creates and calls from in SAS Programming</title>
    <link>https://communities.sas.com/t5/SAS-Programming/List-tables-code-creates-and-calls-from/m-p/747390#M234566</link>
    <description>&lt;P&gt;I think you have to examine the code itself.&amp;nbsp; Dictionary.Tables will tell you what tables exist after you've run your code, but I don't believe you can use Dictionary.Tables to predict what a given piece of SAS code will create.&amp;nbsp; I would parse the SAS code itself.&amp;nbsp;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;First, I would create a little dataset containing all my Librefs, then I would TRANSPOSE the data so that each Libref is in its own column.&amp;nbsp; Like so:&lt;/P&gt;
&lt;PRE&gt;&lt;CODE class=" language-sas"&gt;DATA	My_Libnames;
	INFILE	DATALINES;
	INPUT	Libname	$;
	CALL	SYMPUTX('Column_Cnt', STRIP(PUT(_N_, 5.)), 'G');
DATALINES;
WORK
PROD01
DEV01
XREF
DB_01
DB_02
DB_03
;
RUN;

**------------------------------------------------------------------------------**;

PROC	TRANSPOSE	DATA=MY_Libnames
					OUT=My_Libnames_As_Cols(DROP=_NAME_);
	VAR LIBNAME;
RUN;&lt;/CODE&gt;&lt;/PRE&gt;
&lt;P&gt;After creating a dataset containing my Libnames, I would read the SAS code I want to know about.&amp;nbsp; Here, I'm using DATALINES4 to bring the SAS code in, but if you have *.sas files, you would modify this code to use an INFILE.&amp;nbsp; Notice that the first three lines of the program are commented out.&amp;nbsp; The first three lines are an alternative method of reading in the data.&amp;nbsp; The first three lines work, but I can do the same thing with two lines if I use the $CHARw. Informat.&amp;nbsp; Not everyone is familiar with the $CHARw. Informat, so I thought it might be worth illustrating.&lt;/P&gt;
&lt;PRE&gt;&lt;CODE class=" language-sas"&gt;DATA	My_SAS_Code;
/*	LENGTH	Line_of_Code	$32767;*/
/*	INPUT;*/
/*	Line_of_Code	=		_INFILE_;*/
	INFILE	DATALINES4		TRUNCOVER;
	INPUT	Line_of_Code	$CHAR32767.;
DATALINES4;
PROC SQL;
CREATE TABLE WORK.Agreement_Data as
Select
t1.*,
t2.*
FROM WORK.Base_Data t1
LEFT JOIN WORK.Agreement_Prep t2
ON t1.Local_Agreement_Identifier = t2.Local_Agreement_Identifier
AND t1.Audit_Request_Identifier = t2.Audit_Request_Identifier
/*AND MISSING(Detail.Audit_Request_Identifier)*/
;
;;;;
RUN;&lt;/CODE&gt;&lt;/PRE&gt;
&lt;P&gt;Then I would create a program similar to the below that would 1) create an array of my Libnames and then 2) search each line of code looking for a match on one of the Libnames in my array of Libnames.&amp;nbsp; When I get a match, I would&amp;nbsp;parse that line of code for the table name.&amp;nbsp; In the below code, I have a line to remove the Libref if needed, but it is commented out.&amp;nbsp; I think it's better to have the Libref included with the table name because you might have a both a WORK.my_very_important_data as well as a PERM.my_very_important_data.&amp;nbsp; As coded, this program would identify both.&amp;nbsp; If you don't want the Libname as part of the table name, uncomment that one line of code.&amp;nbsp; This program could be combined with the previous program that reads the SAS code but is here separated so that it's a little easier to see what I'm doing.&lt;/P&gt;
&lt;PRE&gt;&lt;CODE class=" language-sas"&gt;DATA	My_Tables(KEEP=Table_Name);
	RETAIN	First_Time	1;
	LENGTH	Table_Name	$128.;

	IF	First_Time				THEN
		DO;
			First_Time		=	0;
			SET	WORK.My_Libnames_As_Cols;
		END;

	ARRAY	My_Libnames	{*}	$8	Col1-Col&amp;amp;Column_Cnt;

	SET	My_SAS_Code;

	DO	i					=	1	TO	&amp;amp;Column_Cnt;
		Libref_Position		=	INDEX(Line_of_Code, STRIP(My_Libnames{i}));
		IF	Libref_Position		THEN
			DO;
				Table_Name	=	SCAN(SUBSTR(Line_of_Code, Libref_Position),1,' ;*');
*				Table_Name	=	TRANWRD(Table_Name, CATS(My_Libnames[i}, '.'), '');
				OUTPUT;
			END;
	END;

	DELETE;
RUN;&lt;/CODE&gt;&lt;/PRE&gt;
&lt;P&gt;&amp;nbsp;Jim&lt;/P&gt;</description>
    <pubDate>Fri, 11 Jun 2021 16:12:21 GMT</pubDate>
    <dc:creator>jimbarbour</dc:creator>
    <dc:date>2021-06-11T16:12:21Z</dc:date>
    <item>
      <title>List tables code creates and calls from</title>
      <link>https://communities.sas.com/t5/SAS-Programming/List-tables-code-creates-and-calls-from/m-p/747344#M234546</link>
      <description>&lt;P&gt;Hello,&lt;/P&gt;&lt;P&gt;I am looking to create a list of tables a program creates (create table) and uses (from or join). My goal is to drop tables when possible but I don't want to drop a table in Program 1 if it's used in Program 2 of the same project.&lt;/P&gt;&lt;P&gt;&amp;nbsp;&lt;/P&gt;&lt;P&gt;I have tried the following code to list work table but I also want to find permanent tables the program is creating and using.&lt;/P&gt;&lt;P&gt;&amp;nbsp;&lt;/P&gt;&lt;PRE&gt;&lt;CODE class=" language-sas"&gt;proc sql ;
create table work_tables as
select *&amp;nbsp;from dictionary.tables
where libname = 'WORK'
order by memname ;
quit ;&lt;/CODE&gt;&lt;/PRE&gt;&lt;P&gt;&amp;nbsp;&lt;/P&gt;&lt;P&gt;From this code, I'd like to see the tables it created and used such as;&lt;/P&gt;&lt;P&gt;work.Agreement_Data&lt;/P&gt;&lt;P&gt;work.Base_Data&lt;/P&gt;&lt;P&gt;work.Agreement_Prep&lt;/P&gt;&lt;PRE&gt;&lt;CODE class=" language-sas"&gt;PROC SQL;
CREATE TABLE WORK.Agreement_Data as
Select
t1.*,
t2.*
FROM WORK.Base_Data t1
LEFT JOIN WORK.Agreement_Prep t2
ON t1.Local_Agreement_Identifier = t2.Local_Agreement_Identifier
AND t1.Audit_Request_Identifier = t2.Audit_Request_Identifier
/*AND MISSING(Detail.Audit_Request_Identifier)*/
;&lt;/CODE&gt;&lt;/PRE&gt;&lt;P&gt;you're time is appreciated.&lt;/P&gt;&lt;P&gt;&amp;nbsp;&lt;/P&gt;&lt;P&gt;&amp;nbsp;&lt;/P&gt;</description>
      <pubDate>Fri, 11 Jun 2021 14:02:11 GMT</pubDate>
      <guid>https://communities.sas.com/t5/SAS-Programming/List-tables-code-creates-and-calls-from/m-p/747344#M234546</guid>
      <dc:creator>stacy_lee</dc:creator>
      <dc:date>2021-06-11T14:02:11Z</dc:date>
    </item>
    <item>
      <title>Re: List tables code creates and calls from</title>
      <link>https://communities.sas.com/t5/SAS-Programming/List-tables-code-creates-and-calls-from/m-p/747367#M234555</link>
      <description>Use PROC SCAPROC and run your code and then check the log. It will have the information in there for you to parse more easily.&lt;BR /&gt;You can then parse out all the INPUT and OUTPUT records to easily filter out your tables required.&lt;BR /&gt;</description>
      <pubDate>Fri, 11 Jun 2021 15:06:53 GMT</pubDate>
      <guid>https://communities.sas.com/t5/SAS-Programming/List-tables-code-creates-and-calls-from/m-p/747367#M234555</guid>
      <dc:creator>Reeza</dc:creator>
      <dc:date>2021-06-11T15:06:53Z</dc:date>
    </item>
    <item>
      <title>Re: List tables code creates and calls from</title>
      <link>https://communities.sas.com/t5/SAS-Programming/List-tables-code-creates-and-calls-from/m-p/747390#M234566</link>
      <description>&lt;P&gt;I think you have to examine the code itself.&amp;nbsp; Dictionary.Tables will tell you what tables exist after you've run your code, but I don't believe you can use Dictionary.Tables to predict what a given piece of SAS code will create.&amp;nbsp; I would parse the SAS code itself.&amp;nbsp;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;First, I would create a little dataset containing all my Librefs, then I would TRANSPOSE the data so that each Libref is in its own column.&amp;nbsp; Like so:&lt;/P&gt;
&lt;PRE&gt;&lt;CODE class=" language-sas"&gt;DATA	My_Libnames;
	INFILE	DATALINES;
	INPUT	Libname	$;
	CALL	SYMPUTX('Column_Cnt', STRIP(PUT(_N_, 5.)), 'G');
DATALINES;
WORK
PROD01
DEV01
XREF
DB_01
DB_02
DB_03
;
RUN;

**------------------------------------------------------------------------------**;

PROC	TRANSPOSE	DATA=MY_Libnames
					OUT=My_Libnames_As_Cols(DROP=_NAME_);
	VAR LIBNAME;
RUN;&lt;/CODE&gt;&lt;/PRE&gt;
&lt;P&gt;After creating a dataset containing my Libnames, I would read the SAS code I want to know about.&amp;nbsp; Here, I'm using DATALINES4 to bring the SAS code in, but if you have *.sas files, you would modify this code to use an INFILE.&amp;nbsp; Notice that the first three lines of the program are commented out.&amp;nbsp; The first three lines are an alternative method of reading in the data.&amp;nbsp; The first three lines work, but I can do the same thing with two lines if I use the $CHARw. Informat.&amp;nbsp; Not everyone is familiar with the $CHARw. Informat, so I thought it might be worth illustrating.&lt;/P&gt;
&lt;PRE&gt;&lt;CODE class=" language-sas"&gt;DATA	My_SAS_Code;
/*	LENGTH	Line_of_Code	$32767;*/
/*	INPUT;*/
/*	Line_of_Code	=		_INFILE_;*/
	INFILE	DATALINES4		TRUNCOVER;
	INPUT	Line_of_Code	$CHAR32767.;
DATALINES4;
PROC SQL;
CREATE TABLE WORK.Agreement_Data as
Select
t1.*,
t2.*
FROM WORK.Base_Data t1
LEFT JOIN WORK.Agreement_Prep t2
ON t1.Local_Agreement_Identifier = t2.Local_Agreement_Identifier
AND t1.Audit_Request_Identifier = t2.Audit_Request_Identifier
/*AND MISSING(Detail.Audit_Request_Identifier)*/
;
;;;;
RUN;&lt;/CODE&gt;&lt;/PRE&gt;
&lt;P&gt;Then I would create a program similar to the below that would 1) create an array of my Libnames and then 2) search each line of code looking for a match on one of the Libnames in my array of Libnames.&amp;nbsp; When I get a match, I would&amp;nbsp;parse that line of code for the table name.&amp;nbsp; In the below code, I have a line to remove the Libref if needed, but it is commented out.&amp;nbsp; I think it's better to have the Libref included with the table name because you might have a both a WORK.my_very_important_data as well as a PERM.my_very_important_data.&amp;nbsp; As coded, this program would identify both.&amp;nbsp; If you don't want the Libname as part of the table name, uncomment that one line of code.&amp;nbsp; This program could be combined with the previous program that reads the SAS code but is here separated so that it's a little easier to see what I'm doing.&lt;/P&gt;
&lt;PRE&gt;&lt;CODE class=" language-sas"&gt;DATA	My_Tables(KEEP=Table_Name);
	RETAIN	First_Time	1;
	LENGTH	Table_Name	$128.;

	IF	First_Time				THEN
		DO;
			First_Time		=	0;
			SET	WORK.My_Libnames_As_Cols;
		END;

	ARRAY	My_Libnames	{*}	$8	Col1-Col&amp;amp;Column_Cnt;

	SET	My_SAS_Code;

	DO	i					=	1	TO	&amp;amp;Column_Cnt;
		Libref_Position		=	INDEX(Line_of_Code, STRIP(My_Libnames{i}));
		IF	Libref_Position		THEN
			DO;
				Table_Name	=	SCAN(SUBSTR(Line_of_Code, Libref_Position),1,' ;*');
*				Table_Name	=	TRANWRD(Table_Name, CATS(My_Libnames[i}, '.'), '');
				OUTPUT;
			END;
	END;

	DELETE;
RUN;&lt;/CODE&gt;&lt;/PRE&gt;
&lt;P&gt;&amp;nbsp;Jim&lt;/P&gt;</description>
      <pubDate>Fri, 11 Jun 2021 16:12:21 GMT</pubDate>
      <guid>https://communities.sas.com/t5/SAS-Programming/List-tables-code-creates-and-calls-from/m-p/747390#M234566</guid>
      <dc:creator>jimbarbour</dc:creator>
      <dc:date>2021-06-11T16:12:21Z</dc:date>
    </item>
    <item>
      <title>Re: List tables code creates and calls from</title>
      <link>https://communities.sas.com/t5/SAS-Programming/List-tables-code-creates-and-calls-from/m-p/747757#M234759</link>
      <description>Reeza, thank you so much. I will have to learn more about Proc SCAPROC as I wasn't able to figure it out.&lt;BR /&gt;&lt;BR /&gt;Jim, thank you as well. I will also have to study how and why this works, but it did.&lt;BR /&gt;&lt;BR /&gt;I appreciate the time and information both of you provided!</description>
      <pubDate>Mon, 14 Jun 2021 11:27:16 GMT</pubDate>
      <guid>https://communities.sas.com/t5/SAS-Programming/List-tables-code-creates-and-calls-from/m-p/747757#M234759</guid>
      <dc:creator>stacy_lee</dc:creator>
      <dc:date>2021-06-14T11:27:16Z</dc:date>
    </item>
  </channel>
</rss>

