The task is to create a successor to a SAS data set, replacing each numeric variable in the original with a character variable. Here is a method which preserves variable order and variable attributes. First create a data set for the demonstration:
proc sql;
create table mixedtype as
 select   name label = 'First Name'
        , sex format = $1.
        , age label = 'Age as of 1 March 2008'
        , height
        , weight format = 6.2
  from sashelp.class;
Result:
                 Age as
                   of 1
First             March
Name      Sex      2008    Height  Weight
-----------------------------------------
Alfred    M          14        69  112.50
Alice     F          13      56.5   84.00
Barbara   F          13      65.3   98.00
Carol     F          14      62.8  102.50
Henry     M          14      63.5  102.50
James     M          12      57.3   83.00
Jane      F          12      59.8   84.50
Janet     F          15      62.5  112.50
Jeffrey   M          13      62.5   84.00
John      M          12        59   99.50
Joyce     F          11      51.3   50.50
Judy      F          14      64.3   90.00
Louise    F          12      56.3   77.00
Mary      F          15      66.5  112.00
Philip    M          16        72  150.00
Robert    M          12      64.8  128.00
Ronald    M          15        67  133.00
Thomas    M          11      57.5   85.00
William   M          15      66.5  112.00
Next, this somewhat tricky query which uses DICTIONARY.COLUMNS as a source of metadata and creates the bulk of another query:
select case type
        when 'num'  then catx (   ' ' 
                                , 'left( put ('
                                , name
                                , ','
                                , case
                                   when format is null then 'best12.' 
                                   else format
                                   end
                                , ') ) as'
                                , name
                                , 'label ='
                                , quote( strip(label) )                               
                              )
        when 'char' then name
        else             catx (   ' '
                                , quote('Error on type')
                                , 'as'
                                , name
                              )
        end
 into : selections separated by ' , '
 from dictionary.columns
 where libname='WORK' and memname='MIXEDTYPE';
To adapt for other tables change only the literals in the WHERE clause.
Result:
Name Sex left( put ( Age , best12. ) ) as Age label = "Age as of 1 March 2008" left( put ( Height , best12. ) ) as Height label = "" left( put ( Weight , 6.2 ) ) as Weight label = ""
The INTO clause takes these expressions and concatenates them into a comma-separated string which it stores in the macro variable SELECTIONS, which in turn is used in the statement which actually does the work:
create table allchar as select &selections from mixedtype; %symdel selections;
Result:
First Age as of 1 Name Sex March 2008 Height Weight ------------------------------------------------- Alfred M 14 69 112.50 Alice F 13 56.5 84.00 Barbara F 13 65.3 98.00 Carol F 14 62.8 102.50 Henry M 14 63.5 102.50 James M 12 57.3 83.00 Jane F 12 59.8 84.50 Janet F 15 62.5 112.50 Jeffrey M 13 62.5 84.00 John M 12 59 99.50 Joyce F 11 51.3 50.50 Judy F 14 64.3 90.00 Louise F 12 56.3 77.00 Mary F 15 66.5 112.00 Philip M 16 72 150.00 Robert M 12 64.8 128.00 Ronald M 15 67 133.00 Thomas M 11 57.5 85.00 William M 15 66.5 112.00
Another query against DICTIONARY.COLUMNS compares the attributes of the original and replacement variables:
select   name    format=$10.
       , memname format=$10.
       , varnum  format=10.
       , type    format=$8.
       , length  format=6.
       , format  format=$8.
       , label   format=$30.
 from dictionary.columns
 where libname='WORK' and memname in ('ALLCHAR','MIXEDTYPE')
 order by varnum, memname desc;
quit;
Result:
Column Column Member Number in Column Column Column Name Name Table Type Length Format Column Label -------------------------------------------------------------------------------------- Name MIXEDTYPE 1 char 8 First Name Name ALLCHAR 1 char 8 First Name Sex MIXEDTYPE 2 char 1 $1. Sex ALLCHAR 2 char 1 $1. Age MIXEDTYPE 3 num 8 Age as of 1 March 2008 Age ALLCHAR 3 char 12 Age as of 1 March 2008 Height MIXEDTYPE 4 num 8 Height ALLCHAR 4 char 12 Weight MIXEDTYPE 5 num 8 6.2 Weight ALLCHAR 5 char 6
This demonstrates that variable order and variable attributes are preserved.
It's finally time to hack! Remember to visit the SAS Hacker's Hub regularly for news and updates.
The rapid growth of AI technologies is driving an AI skills gap and demand for AI talent. Ready to grow your AI literacy? SAS offers free ways to get started for beginners, business leaders, and analytics professionals of all skill levels. Your future self will thank you.