SAS警告:CREATETABLE语句递归引用目标表

SAS警告:CREATETABLE语句递归引用目标表,sas,proc-sql,Sas,Proc Sql,SAS允许创建proc sqlcreate table语句,其中要创建的表在select语句中递归引用自身,例如: proc sql; create table t1 as select t1.id ,t2.val1 from t1 inner join t2 on t1.id=t2.id ; quit; 当执行这样的语句时,会向日志中写入一条警告消息 警告:此CREATETABLE语

SAS允许创建
proc sql
create table
语句,其中要创建的表在select语句中递归引用自身,例如:

proc sql;
     create table t1 as 
     select 
         t1.id
         ,t2.val1 
     from 
         t1
         inner join t2 on t1.id=t2.id
;
quit;
当执行这样的语句时,会向日志中写入一条警告消息

警告:此CREATETABLE语句递归引用目标表。这可能导致数据完整性问题。

使用
undo\u policy=none
选项可以抑制此警告消息。(见附件)

问题:

  • 以这种递归方式创建表可能会返回一些意外的结果吗?将同一操作分为两个步骤是否可能产生不同的结果:

     proc sql;
       create table _data_ as 
         select 
           t1.id
           ,t2.val1 
         from 
           t1
           inner join t2 on t1.id=t2.id;
    
         create table t1 as
           select * from &syslast;
    
    quit;
    
  • 两步法使用是否更好/更安全


如果要查询的表是SAS数据集,那么这应该可以正常工作。这并不比这个简单的数据步骤更糟糕

data t1;
 merge t1 t2;
 by id;
run;
当SAS运行该类型的步骤时,它将首先使用结果创建一个新的物理文件,只有在该步骤完成后,它才会删除旧的
t1.sas7bdat
,并将临时文件重命名为
t1.sas7bdat
。如果使用PROC SQL语句,SAS将遵循相同的基本步骤


我认为警告是存在的,因为如果引用的表来自外部数据库系统(如Oracle),则SAS可能会将查询推入数据库,并在那里引发问题。

我发现,使用与SAS proc sql输入和输出相同的表名可能会产生不正确的结果。它在大多数情况下工作正常,但绝对不是100%的时间。使用不同的输出表名称,而不是抑制警告


SAS承认了这一点:

不知道您将从这个无效查询中“期望”得到什么结果,很难说它是否会返回“意外”结果。SAS proc sql不支持递归查询。@GordonLinoff-从我目前看到的情况来看,它产生的输出与两步方法相同,我不确定结果是否具有确定性。我继承了一些sas代码,我正在努力理解它。我认为这取决于使用的引擎。基本引擎(您在工作库中使用的)在后台创建一个临时数据集,然后在最后复制它。其他引擎可能不会这样做,因此发出警告。我也收到了这个警告,但我还没有看到任何异常结果。开发人员必须知道可能返回坏结果的非常具体的情况,并将免责声明放在以防万一的地方。我试着使一些最糟糕的递归sql语句成为可能,但没有得到错误的结果。就我个人而言,我会避免它。它可能在99.9999%的时间内工作,但是如果您使用的是关键数据,那么您需要绝对确保读/写操作在100%的时间内都能工作。如果您想这样做,我建议使用数据步骤。数据步骤确实支持这些递归更新操作等。如果将来确实出了问题,即使sql语句不是故障的确切原因,也要比“我忽略了这个警告,但这可能没有关系”更容易向上司解释。)谢谢你@tom的回答,这正是我所怀疑的。令我担忧的是警告消息中的一部分,该部分声明“这可能导致数据完整性问题”,并且可以使用“undo_policy=none”选项抑制警告消息。SAS文档并不十分清楚——至少从我所看到的情况来看——这种类型的语句何时可以安全使用,以及在哪些情况下会导致问题。如果它会导致数据完整性问题,那么首先为什么要允许它。