Macros for SAS Application Developers
https://github.com/sasjs/core
Loading...
Searching...
No Matches
mp_md5.sas
Go to the documentation of this file.
1/**
2 @file
3 @brief Generates an md5 expression for hashing a set of variables
4 @details This is the same algorithm used to hash records in
5 [Data Controller for SAS](https://datacontroller.io).
6
7 It is not designed to be efficient - it is designed to be effective,
8 given the range of edge cases (large floating points, special missing
9 numerics, thousands of columns, very wide columns).
10
11 It can be used only in data step, eg as follows:
12
13 data _null_;
14 set sashelp.class;
15 hashvar=%mp_md5(cvars=name sex, nvars=age height weight);
16 put hashvar=;
17 run;
18
19 Unfortunately it will not run in SQL - it fails with the following message:
20
21 > The width value for HEX is out of bounds. It should be between 1 and 16
22
23 The macro will also cause errors if the data contains (non-special) missings
24 and the (undocumented) `options dsoptions=nonote2err;` is in effect.
25
26 This can be avoided in two ways:
27
28 @li Global option: `options dsoptions=nonote2err;`
29 @li Data step option: `data YOURLIB.YOURDATASET /nonote2err;`
30
31 For very wide tables (hundreds or thousands of columns) consider using
32 `mp_rowhash.sas`, which builds the same type of row hash iteratively and
33 avoids creating a single, very long concatenated SAS expression.
34
35 @param [in] cvars= () Space seperated list of character variables
36 @param [in] nvars= () Space seperated list of numeric variables
37
38 <h4> Related Programs </h4>
39 @li mp_init.sas
40 @li mp_rowhash.sas
41
42 @version 9.2
43 @author Allan Bowe
44**/
45
46%macro mp_md5(cvars=,nvars=);
47%local i var sep;
48put(md5(
49 %do i=1 %to %sysfunc(countw(&cvars));
50 %let var=%scan(&cvars,&i,%str( ));
51 &sep put(md5(trim(&var)),$hex32.)
52 %let sep=!!;
53 %end;
54 %do i=1 %to %sysfunc(countw(&nvars));
55 %let var=%scan(&nvars,&i,%str( ));
56 /* multiply by 1 to strip precision errors (eg 0 != 0) */
57 /* but ONLY if not missing, else will lose any special missing values */
58 &sep put(md5(trim(put(ifn(missing(&var),&var,&var*1),binary64.))),$hex32.)
59 %let sep=!!;
60 %end;
61),$hex32.)
62%mend mp_md5;