Macros for SAS Application Developers
https://github.com/sasjs/core
Loading...
Searching...
No Matches
mp_getconstraints.sas
Go to the documentation of this file.
1/**
2 @file mp_getconstraints.sas
3 @brief Get constraint details at column level
4 @details Useful for capturing constraints before they are dropped / reapplied
5 during an update.
6
7 proc sql;
8 create table work.example(
9 TX_FROM float format=datetime19.,
10 DD_TYPE char(16),
11 DD_SOURCE char(2048),
12 DD_SHORTDESC char(256),
13 constraint pk primary key(tx_from, dd_type,dd_source),
14 constraint unq unique(tx_from, dd_type),
15 constraint nnn not null(DD_SHORTDESC)
16 );
17
18 %mp_getconstraints(lib=work,ds=example,outds=work.constraints)
19
20 @param [in] lib= (WORK) The target library
21 @param [in] ds= The target dataset. Leave blank (default) for all datasets.
22 @param [in] mdebug= (0) Set to 1 to preserve temp tables, print var values etc
23 @param [out] outds= (mp_getconstraints) the output dataset
24
25 <h4> SAS Macros </h4>
26 @li mf_getuniquename.sas
27 @li mp_dropmembers.sas
28
29 @version 9.2
30 @author Allan Bowe
31
32 @sasjslint {"maxLineLength": 123}
33**/
34
35%macro mp_getconstraints(lib=WORK
36 ,ds=
37 ,outds=mp_getconstraints
38 ,mdebug=0
39)/*/STORE SOURCE*/;
40
41%let lib=%upcase(&lib);
42%let ds=%upcase(&ds);
43
44/**
45 * Cater for environments where sashelp.vcncolu is not available
46 */
47%if %sysfunc(exist(sashelp.vcncolu,view))=0 %then %do;
48 proc sql;
49 create table &outds(
50 libref char(8)
51 ,TABLE_NAME char(32)
52 ,constraint_type char(8) label='Constraint Type'
53 ,constraint_name char(32) label='Constraint Name'
54 ,column_name char(32) label='Column'
55 ,constraint_order num
56 );
57 %return;
58%end;
59
60/**
61 * Neither dictionary tables nor sashelp provides a constraint order column,
62 * however they DO arrive in the correct order. So, create the col.
63 **/
64%local vw;
65%let vw=%mf_getuniquename(prefix=mp_getconstraints_vw_);
66data &vw /view=&vw;
67 set sashelp.vcncolu;
68 where table_catalog="&lib";
69
70 /* use retain approach to reset the constraint order with each constraint */
71 length tmp $1000;
72 retain tmp;
73 drop tmp;
74 if tmp ne catx('|',table_catalog,table_name,constraint_name) then do;
75 constraint_order=1;
76 end;
77 else constraint_order+1;
78 tmp=catx('|',table_catalog, table_name,constraint_name);
79run;
80
81/* must use SQL as proc datasets does not support length changes */
82proc sql noprint;
83create table &outds as
84 select upcase(a.TABLE_CATALOG) as libref
85 ,upcase(a.TABLE_NAME) as TABLE_NAME
86 ,a.constraint_type
87 ,a.constraint_name
88 ,b.column_name
89 ,b.constraint_order
90 from dictionary.TABLE_CONSTRAINTS a
91 left join &vw b
92 on upcase(a.TABLE_CATALOG)=upcase(b.TABLE_CATALOG)
93 and upcase(a.TABLE_NAME)=upcase(b.TABLE_NAME)
94 and a.constraint_name=b.constraint_name
95/**
96 * We cannot apply this clause to the underlying dictionary table. See:
97 * https://communities.sas.com/t5/SAS-Programming/Unexpected-Where-Clause-behaviour-in-dictionary-TABLE/m-p/771554#M244867
98 * cannot use`where calculated libref="&lib"` either as it will STILL execute
99 * all the underlying constraint queries, causing exception errors in some
100 * cases: https://github.com/sasjs/core/issues/283
101 */
102 where a.TABLE_CATALOG="&lib"
103 %if "&ds" ne "" %then %do;
104 and upcase(a.TABLE_NAME)="&ds"
105 and upcase(b.TABLE_NAME)="&ds"
106 %end;
107 order by libref, table_name, constraint_name, constraint_order
108 ;
109
110/* tidy up */
111%mp_dropmembers(
112 &vw,
113 iftrue=(&mdebug=0)
114)
115
116%mend mp_getconstraints;