As the first step in the decommissioning of sasCommunity.org the site has been converted to read-only mode.
Here are some tips for How to share your SAS knowledge with your professional network.
Thank you for posting this! It's so obvious, now, that you've pointed out WHY it is this way. Now my PROC EXPORT will look the way I want!.--Nancy Wilson
The retain statement is not one to be used without understanding the implications. It is a beast that nexer rests. It can live years without raising it's head but given the opportunity, it will wreak havok. You may not be the one that loses hours of sleep trying to figure out what happened, why the data is suddenly wrong, or the program is acting different. The retain statement opens the door to hold data from one record to be used later. It is not respective of account boundaries, personal information, or anything else you might assume would constrain it. You must keep it in it's cage and using it without realizing that at some later date someone could add one line of code that will release the beast from it's cage. Use the length statement or the attrib statement but if you use the retain, you better put comments that NO logic goes in that step. I am working for an international/global company that bought into the fact it is harmless. It is a HUGE liability because it does not take much for it to copy or add data to subsequent records. PLEASE, PLEASE, PLEASE use it with caution. It may be convenient but it is not without consequences.--Geometeacherspet
There seems to be a disparity of advice here. Using RETAIN as a variable reordering device is safe; no, it's to be avoided. The truth probably depends on unstated assumptions. All of the variables to be reordered are inherited from existing data sets; no, some might be newly created, or future code modification might change their status. As in a lot of situations, absolute advice is probably not good advice. So use code that works, and include comments to express critical assumptions and to flag usage of features for secondary or side effects.--Howles 23:48, 11 September 2011 (UTC)
Geometeacherspet seems to doubt that inherited variables are retained. Here's a step demonstrating that they in fact are.
data _null_ ; put _n_= 'Top ' inherited_var= noninherited_var= ; set sashelp.class(rename = ( age = inherited_var ) obs=1 ) ; noninherited_var = 22 ; put _n_= 'Bottom ' inherited_var= noninherited_var= ; run ;
--Howles 23:48, 11 September 2011 (UTC)
One suggestion is to use an ATTRIB statement of the form
attrib a b ;
That is, an ATTRIB statement which names variables but does not assign any attributes. This raises an ERROR condition. That's too bad, because if SAS permitted such a construct, it would be the holy grail that reorders any mixture of inherited and non-inherited variables, with no side effects other than the possible loss of case pattern in the variable names.--Howles 23:48, 11 September 2011 (UTC)
I have recently asked SAS to add some variable ordering tools:
- a REORDER statement in PROC DATASETS
- a REORDER data set option
- a REORDER statement in the DATA step which would be equivalent to using the data set option on all data sets being created (similar to the relationship of the RENAME data set option and statement).
- a PDVORDER statement which would work like the ATTRIB statement might, but doesn't, when it specifies no attributes.
--Howles 23:48, 11 September 2011 (UTC)
SET RETAINs Variables
It's redundant to use a RETAIN statement on vars from a SET dataset as all SET vars are automatically RETAINed. RETAIN is for vars created in an INPUT or assignment statement. See SAS 9.2 documentation at the link below; look for "Redundancy"... RETAIN Statement
--Jpotelle 12:20, 9 January 2012 (EST)
Better explanation of dangers of RETAIN
It's *generally* safe, in good code. But remember that the vast majority of the users of this wiki are people who are new to the language (I won't need to look up how to do this, for instance, so I'll never come here) - and for them, the EXACT danger should be outlined, rather than a flat but unspecified warning that "any code is bad!".
example of code which is bad:
data WANT; retain c b a; /* set up column order */ set HAVE (keep = a b); if a = 1 then c = 1; /* C is retained, but since it does NOT exist in the source dataset this results in potentially undesirable behavior - the assigned value (1) will propagate to all future rows rather than being replaced with the new value from the dataset */ run;
But any operations on A or B (or any un-retained variables) are perfectly safe.
--YB 12:30, 13 March 2013 (EST)