<?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: Capture SQL View Definition for Programmatic Change in SAS Programming</title>
    <link>https://communities.sas.com/t5/SAS-Programming/Capture-SQL-View-Definition-for-Programmatic-Change/m-p/989561#M380216</link>
    <description>&lt;P&gt;Hi&amp;nbsp;&lt;a href="https://communities.sas.com/t5/user/viewprofilepage/user-id/11562"&gt;@Kurt_Bremser&lt;/a&gt;&amp;nbsp;&lt;BR /&gt;&lt;BR /&gt;Thanks for answering.&amp;nbsp;&lt;BR /&gt;&lt;BR /&gt;There are no explicit scripts. The views get created metadata driven. Below an example of the main "table" for this.&lt;/P&gt;
&lt;P&gt;&lt;span class="lia-inline-image-display-wrapper lia-image-align-inline" image-alt="Patrick_0-1781171674183.png" style="width: 1714px;"&gt;&lt;img src="https://communities.sas.com/t5/image/serverpage/image-id/115796iDE863B9204FD35BE/image-dimensions/1714x257?v=v2" width="1714" height="257" role="button" title="Patrick_0-1781171674183.png" alt="Patrick_0-1781171674183.png" /&gt;&lt;/span&gt;&lt;/P&gt;
&lt;P&gt;What I'm trying to do, is to create the data environment for an integration environment using the data from source that has been defined as "source of truth" and against which data needs to get reconciled (after running for another month).&lt;/P&gt;
&lt;P&gt;In theory I wouldn't have to bother about the views, because they should get re-created by such a run. ...but one can't be sure.&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;I could of course use the config Excels and the existing scripts from source to build some adhoc job for re-creating the views in the target environment, BUT... I really would like to avoid this. Things are done messy.&amp;nbsp;&lt;BR /&gt;What I would like to do, is to create the data (views included) for this integration environment without any dependency on any version of Excel config sheets or scripts.&lt;BR /&gt;&lt;BR /&gt;&lt;/P&gt;
&lt;P&gt;I hope this explains why I'm trying to extract and use the view definitions to re-create the views.&amp;nbsp;&lt;BR /&gt;&lt;BR /&gt;Regards, Patrick&lt;/P&gt;</description>
    <pubDate>Thu, 11 Jun 2026 10:15:13 GMT</pubDate>
    <dc:creator>Patrick</dc:creator>
    <dc:date>2026-06-11T10:15:13Z</dc:date>
    <item>
      <title>Capture SQL View Definition for Programmatic Change</title>
      <link>https://communities.sas.com/t5/SAS-Programming/Capture-SQL-View-Definition-for-Programmatic-Change/m-p/989544#M380211</link>
      <description>&lt;P&gt;Hi Experts,&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;I need to replicate a SAS 9.4 data environment in a Linux environment. Using rsync -av works like a charm for this.&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;The challenge I'm facing is that the source environment also contains SQL views in the form:&lt;/P&gt;
&lt;PRE&gt;select *
from lref.table
using libname lref "&amp;lt;source_root_path&amp;gt;/&amp;lt;relative path&amp;gt;";&lt;/PRE&gt;
&lt;P&gt;I need to re-create these views in the target environment by replacing the source_root_path with the target_root_path.&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;Do you know of any other/better way than executing a SQL describe view, capture the log output in a file, parse out the view definition, change the path and then use this new code to create the views in the target environment?&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;I couldn't figure out any other way to retrieve the view definition.&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;Thanks, Patrick&lt;/P&gt;</description>
      <pubDate>Thu, 11 Jun 2026 08:50:30 GMT</pubDate>
      <guid>https://communities.sas.com/t5/SAS-Programming/Capture-SQL-View-Definition-for-Programmatic-Change/m-p/989544#M380211</guid>
      <dc:creator>Patrick</dc:creator>
      <dc:date>2026-06-11T08:50:30Z</dc:date>
    </item>
    <item>
      <title>Re: Capture SQL View Definition for Programmatic Change</title>
      <link>https://communities.sas.com/t5/SAS-Programming/Capture-SQL-View-Definition-for-Programmatic-Change/m-p/989546#M380213</link>
      <description>&lt;P&gt;UNIX systems have very nice tools for exactly such mass text change operations, e.g. awk. Just run that on the original source codes of the SQL views. If those source codes are not available, someone fucked up big time (see Maxim 27).&lt;/P&gt;</description>
      <pubDate>Thu, 11 Jun 2026 09:00:59 GMT</pubDate>
      <guid>https://communities.sas.com/t5/SAS-Programming/Capture-SQL-View-Definition-for-Programmatic-Change/m-p/989546#M380213</guid>
      <dc:creator>Kurt_Bremser</dc:creator>
      <dc:date>2026-06-11T09:00:59Z</dc:date>
    </item>
    <item>
      <title>Re: Capture SQL View Definition for Programmatic Change</title>
      <link>https://communities.sas.com/t5/SAS-Programming/Capture-SQL-View-Definition-for-Programmatic-Change/m-p/989561#M380216</link>
      <description>&lt;P&gt;Hi&amp;nbsp;&lt;a href="https://communities.sas.com/t5/user/viewprofilepage/user-id/11562"&gt;@Kurt_Bremser&lt;/a&gt;&amp;nbsp;&lt;BR /&gt;&lt;BR /&gt;Thanks for answering.&amp;nbsp;&lt;BR /&gt;&lt;BR /&gt;There are no explicit scripts. The views get created metadata driven. Below an example of the main "table" for this.&lt;/P&gt;
&lt;P&gt;&lt;span class="lia-inline-image-display-wrapper lia-image-align-inline" image-alt="Patrick_0-1781171674183.png" style="width: 1714px;"&gt;&lt;img src="https://communities.sas.com/t5/image/serverpage/image-id/115796iDE863B9204FD35BE/image-dimensions/1714x257?v=v2" width="1714" height="257" role="button" title="Patrick_0-1781171674183.png" alt="Patrick_0-1781171674183.png" /&gt;&lt;/span&gt;&lt;/P&gt;
&lt;P&gt;What I'm trying to do, is to create the data environment for an integration environment using the data from source that has been defined as "source of truth" and against which data needs to get reconciled (after running for another month).&lt;/P&gt;
&lt;P&gt;In theory I wouldn't have to bother about the views, because they should get re-created by such a run. ...but one can't be sure.&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;I could of course use the config Excels and the existing scripts from source to build some adhoc job for re-creating the views in the target environment, BUT... I really would like to avoid this. Things are done messy.&amp;nbsp;&lt;BR /&gt;What I would like to do, is to create the data (views included) for this integration environment without any dependency on any version of Excel config sheets or scripts.&lt;BR /&gt;&lt;BR /&gt;&lt;/P&gt;
&lt;P&gt;I hope this explains why I'm trying to extract and use the view definitions to re-create the views.&amp;nbsp;&lt;BR /&gt;&lt;BR /&gt;Regards, Patrick&lt;/P&gt;</description>
      <pubDate>Thu, 11 Jun 2026 10:15:13 GMT</pubDate>
      <guid>https://communities.sas.com/t5/SAS-Programming/Capture-SQL-View-Definition-for-Programmatic-Change/m-p/989561#M380216</guid>
      <dc:creator>Patrick</dc:creator>
      <dc:date>2026-06-11T10:15:13Z</dc:date>
    </item>
    <item>
      <title>Re: Capture SQL View Definition for Programmatic Change</title>
      <link>https://communities.sas.com/t5/SAS-Programming/Capture-SQL-View-Definition-for-Programmatic-Change/m-p/989583#M380219</link>
      <description>&lt;P&gt;AI had a reasonable suggestion:&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;&lt;EM&gt;In your target environment, could you create a symlink that points&amp;nbsp;&amp;nbsp;source_root_path&amp;nbsp; to target_root_path?&lt;/EM&gt;&lt;/P&gt;
&lt;P&gt;&lt;BR /&gt;That would avoid code changes.&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;AI also generated a macro to implement the log capture approach you mentioned.&amp;nbsp; This is #AI and #UNTESTED, but from a quick skim read doesn't look crazy.&amp;nbsp; The AI was running this on windows SAS, not linux, so would likely need to be refined...&amp;nbsp;&lt;BR /&gt;&lt;BR /&gt;&lt;/P&gt;
&lt;PRE&gt;&lt;CODE class=" language-sas"&gt;%macro export_sql_views_with_path_map(
  lib=,
  outcode=,
  source_root=,
  target_root=,
  execute=no,
  include=,
  exclude=
);
  %local execute_uc view_count;

  %let execute_uc=%upcase(%superq(execute));

  %if %superq(lib)= %then %do;
    %put ERROR: (export_sql_views_with_path_map) LIB= is required.;
    %return;
  %end;

  %if %superq(outcode)= %then %do;
    %put ERROR: (export_sql_views_with_path_map) OUTCODE= is required.;
    %return;
  %end;

  %if %superq(source_root)= %then %do;
    %put ERROR: (export_sql_views_with_path_map) SOURCE_ROOT= is required.;
    %return;
  %end;

  %if %superq(target_root)= %then %do;
    %put ERROR: (export_sql_views_with_path_map) TARGET_ROOT= is required.;
    %return;
  %end;

  %if &amp;amp;execute_uc ne YES and &amp;amp;execute_uc ne NO %then %do;
    %put ERROR: (export_sql_views_with_path_map) EXECUTE= must be YES or NO.;
    %return;
  %end;

  proc sql noprint;
    create table work._esv_views as
    select libname
          ,memname
    from dictionary.tables
    where libname = upcase("%superq(lib)")
      and memtype = 'VIEW'
      %if %superq(include) ne %then %do;
      and upcase(memname) like upcase("%superq(include)")
      %end;
      %if %superq(exclude) ne %then %do;
      and upcase(memname) not like upcase("%superq(exclude)")
      %end;
    order by memname
    ;

    select count(*)
      into :view_count trimmed
    from work._esv_views
    ;
  quit;

  %if &amp;amp;view_count = 0 %then %do;
    %put WARNING: (export_sql_views_with_path_map) No views matched in LIB=&amp;amp;lib..;
    %return;
  %end;

  filename esvdesc temp lrecl=32767 encoding='utf-8';
  filename esvdrv  temp lrecl=32767 encoding='utf-8';
  filename esvout  "%superq(outcode)" lrecl=32767 encoding='utf-8';

  data _null_;
    file esvdrv;
    put 'proc sql;';
    set work._esv_views end=last;
    put '  describe view ' libname '.' memname ';';
    if last then put 'quit;';
  run;

  proc printto log=esvdesc new;
  run;

  %include esvdrv;

  proc printto;
  run;

  data work._esv_view_lines;
    length raw $32767 line $32767 view_name $41 libname $8 memname $32;
    infile esvdesc lrecl=32767 truncover;
    input raw $char32767.;

    raw = prxchange('s/\x0c//o', -1, raw);
    raw = tranwrd(raw, '0D'x, ' ');

    retain capture 0 seq 0 view_name libname memname;

     if scan(strip(raw), 1, ' ') = 'NOTE:'
       and scan(strip(raw), 2, ' ') = 'SQL'
       and scan(strip(raw), 3, ' ') = 'view'
       and upcase(scan(strip(raw), 5, ' ')) in ('IS', 'HAS')
    then do;
      view_name = scan(strip(raw), 4, ' ');
      libname = scan(view_name, 1, '.');
      memname = scan(view_name, 2, '.');
      capture = 1;
      seq = 0;
      return;
    end;

    if capture then do;
      if prxmatch('/^\s*\d+\s+The SAS System\b/i', raw) then return;

      line = raw;
      seq + 1;
      output;

      if strip(raw) = ';' then do;
        capture = 0;
      end;
    end;

    keep libname memname view_name seq line;
  run;

  proc sql noprint;
    select count(*)
      into :view_count trimmed
    from work._esv_view_lines
    ;
  quit;

  %if &amp;amp;view_count = 0 %then %do;
    %put ERROR: (export_sql_views_with_path_map) No DESCRIBE VIEW text was captured.;
    %return;
  %end;

  proc sort data=work._esv_view_lines;
    by view_name seq;
  run;

  data _null_;
    if fexist('esvout') then do;
      rc = fdelete('esvout');
      if rc ne 0 then put 'ERROR: (export_sql_views_with_path_map) Unable to replace existing output file.';
    end;
  run;

  data _null_;
    set work._esv_view_lines end=last;
    by view_name seq;

    file esvout;

    if _n_ = 1 then do;
      put '/* Generated by %export_sql_views_with_path_map */';
      put 'proc sql;';
    end;

    length rewritten $32767;
    rewritten = tranwrd(line, symget('source_root'), symget('target_root'));

    if index(symget('target_root'), '/') then do;
      rewritten = tranwrd(rewritten, '\', '/');
    end;

    if first.view_name then do;
      put;
      put '  create view ' view_name ' as';
    end;
    put rewritten;

    if last then put 'quit;';
  run;

  %if &amp;amp;execute_uc = YES %then %do;
    %include esvout;
  %end;

  %put NOTE: (export_sql_views_with_path_map) Processed &amp;amp;view_count lines for LIB=&amp;amp;lib..;
  %put NOTE: (export_sql_views_with_path_map) Output written to %superq(outcode).;
%mend export_sql_views_with_path_map;&lt;/CODE&gt;&lt;/PRE&gt;
&lt;P&gt;&lt;BR /&gt;&lt;BR /&gt;&lt;/P&gt;</description>
      <pubDate>Thu, 11 Jun 2026 20:57:18 GMT</pubDate>
      <guid>https://communities.sas.com/t5/SAS-Programming/Capture-SQL-View-Definition-for-Programmatic-Change/m-p/989583#M380219</guid>
      <dc:creator>Quentin</dc:creator>
      <dc:date>2026-06-11T20:57:18Z</dc:date>
    </item>
  </channel>
</rss>

