在 PROC SQL 中创建的宏变量是局部变量还是全局变量

Does a macro variable created in PROC SQL become local or global

当我写的时候:

proc sql;
    select count(*) into :out from sashelp.cars;
quit;

宏变量out是成为全局变量还是局部变量?

要看你在哪里定义这个宏变量,如果是在宏程序中定义的,就是局部宏变量,否则就是全局宏变量。

视情况而定。让我们组合一个测试宏,看看会发生什么

%macro test();
proc sql noprint;
select count(*) into :x from sashelp.cars;
quit;
%put IN MACRO: &x;
%mend;

options nosource nonotes;

%symdel x;

%test();

%put Out MACRO: &x;

%let x=2;

%put Out MACRO: &x;

%test();

%put Out MACRO: &x;

创建:

IN MACRO:      428
WARNING: Apparent symbolic reference X not resolved.
Out MACRO: &x
Out MACRO: 2
IN MACRO:      428
Out MACRO:      428

所以一开始是没有X宏变量的。 %test() 宏填充了一个局部变量。它在宏外不可用。

之后,我们设置%let x=2使X成为一个全局变量。然后我们执行 %test() 宏,看到 X 将其值保留在 %test() 宏之外。

所以如果它全局存在,它会继续存在并被覆盖。如果它在全球范围内不存在,它将继续在全球范围内不存在。

让我们看一下文档来有力地回答这个问题。

documentation for SQL INTO clause in the Macro language dictionary 说:

Macro variables created with INTO follow the scoping rules for the %LET statement. For more information, see Scopes of Macro Variables.

所以,我们点击 link,找到 this page - How Macro Variables are Assigned and Resolved and this page - Examples of Macro Variable Scopes

第一页有一个很好的树形图,显示了 SAS 在分配或创建宏变量时所做的决定,这可能足以理解这一点。

第二页有一些很好的例子和解释:

When the macro processor executes a macro program statement that can create a macro variable (such as a %LET statement), the macro processor attempts to change the value of an existing macro variable rather than create a new macro variable. The %GLOBAL and %LOCAL statements are exceptions.

那个页面上有一些很好的例子;不过,归根结底很简单。如果已经存在一个具有该名称的宏变量,它会将值分配给该宏变量,无论该变量位于何处 - 在当前宏的作用域树中。 (因此,执行的单个宏有两个符号 table 要查找:本地和全局。另一个宏调用的宏有三个:本地、调用宏的本地和全局等。)

但是,有一对相关的例外:当您指定要使用table时,使用%local%global。在 %letselect into 之前引用宏变量的这些语句中的任何一个都会导致以下任何语句设置该特定版本 - 本地或全局 - 然后你肯定是安全的。