无法在数据步骤中运行Call Execute

时间:2012-10-16 22:50:51

标签: sql sas

我正在尝试在数据步骤中运行insert语句来填充表。运行代码错误时出现以下错误:域错误。日志中没有关于此错误的其他信息。

我正在实施的示例代码是:

  DATA _NULL_;
  SET DataSetA;

 Call Execute ('Proc Sql; Insert Into TableA Select col1,col2,c.Col2 From Table B Inner        Join ( Select col1,' || Datasetcol1 || ' As col2, ' || Datasetcol2 || ' as Col3 FROM ' || Datasetcol3 || ' ) c On b.Col1=c.col1;quit;');

 run;

如果有2000条记录,此代码运行正常,但现在我有10000条记录,并将该错误抛给我。 Datasetcol1和Datasetcol2是我在查询中使用的数据集中的值。

我不知道为什么会出现这种错误。最初,我认为可能是因为处理器工作太多,我通过使用睡眠和唤醒等待,但是,我仍然得到错误。另外,我总是不会得到这个错误。它有时会发生,有时也不会发生。

7 个答案:

答案 0 :(得分:2)

我正在运行Joe的代码,我没有任何问题。这是在带有SAS 9.2m3的Windows 7上,因此可能与您的环境不同。此外,由于我没有你的数据,我无法复制你所做的事情。

我看到许多可能改进代码的东西,但错误消息表明SAS内部存在一些问题。我通常会发现使用SAS Tech支持更有效率,而不是推测黑盒子中可能发生的事情,称为SAS。提交此票。

我在SAS支持网站上对此错误消息做了很好的引用,指出了Oracle特定问题。 http://support.sas.com/kb/14/873.html

答案 1 :(得分:1)

首先,我尝试删除'PROC SQL;'和'退出;'从你重复的CALL EXECUTE开始,每次只运行一次 - 使用IF N = 1;运行PROC SQL,您可以使用LAST变量来确定何时调用QUIT,或者只是将其从datastep中删除并写入QUIT;运行后;数据步骤,然后在适当的地方执行。重复调用SQL环境可能会导致问题本身。

另一种可能的解决方案是使用CALL EXECUTE,将这些全部写入文本文件,然后%包含该文本文件。同样,%包括不包括PROC SQL和QUIT的部分,%include包含在PROC SQL块中。如果CALL EXECUTE在这里特别有问题,那么这就解决了这个问题,而且功能没有区别。老实说,我更喜欢这种方法,因为它更接近你正在做的事情(以编程方式编写SQL代码,然后执行它),以及b)更容易调试(它写入一个文本文件,然后你可以从中获取行测试)。

编辑:从调用中删除PROC SQL和QUIT的示例:

data class;
set sashelp.class;
run;

filename _null dummy;
proc printto log=_null;
data _null_;
set sashelp.class end=eof;
if _n_ = 1 then call execute('PROC SQL;');
do _t = 1 to 10000;
  _exec = cats('insert into class (name,age,sex) select name,age,sex from sashelp.class where name="',name,'";');
  call execute(_exec);
end;

if eof then call execute('QUIT;');
run;

答案 2 :(得分:0)

我认为你的原因是因为call execute的扩展问题。限制可以通过各种各样的事情来确定,例如可用内存量,指令队列的限制(我做了那个btw)等等。

在这种情况下,一个好的做法可能是使用数据集集合语句中的firstobsobs选项以1000个批量处理调用。

DATA _NULL_;
  SET DataSetA(firstobs=1 obs=1000);
  *Call Execute ...;
run;

DATA _NULL_;
  SET DataSetA(firstobs=1001 obs=2000);
  *Call Execute ...;
run;

然后根据需要宏观上述代码...

答案 3 :(得分:0)

对于如此庞大的代码生成,更安全的方法是生成外部文件并运行它:

 DATA _NULL_;
  SET DataSetA;
  file "script.sas";
  length stmt $200;
  stmt = 'Proc Sql; Insert Into TableA Select col1,col2,col3 From Table B Inner        Join ( Select col1,' || Datasetcol1 || ' As col2, ' || Datasetcol2 || ' as Col3 FROM Table C) c On b.Col1=c.col1;quit;';
  put stmt;
 run;

 %include "script.sas" ;

这也为您提供了在处理代码时检查生成的代码的位置。

注意:请注意保存代码的变量(此处为stmt $200)和外部文件的lineize的长度(默认为256)。

答案 4 :(得分:0)

您可以通过宏工具完成所有操作,从而完全避免使用call execute

示例:

%macro InsertFromTable(table_name, ds_col1, ds_col2);
    proc sql;
        Insert Into TableA 
        Select col1,col2,col3 
        From Table B 
        Inner Join ( 
            Select col1
                ,&ds_col1. As col2
                ,&ds_col2. as Col3 
            FROM &table_name. as C
        ) c On b.Col1=c.col1
    ;quit;
%mend;


%Macro InsertFromAllTables();
    %let dsid=%sysfunc(open(DataSetA,i));
    %syscall set(dsid);

    %let rc = %sysfunc(fetch(&dsid));
       %do %while (&rc. eq 0);            
            %InsertFromTable(&table_name., &col1., &col2.);
            %let rc = %sysfunc(fetch(&dsid));            
       %end;
    %let rc=%sysfunc(close(&dsid));
%mend;


data DatasetA;
    infile datalines firstobs=3 missover;    
    input table_name: $10. col1: $10. col2: $10.;

    datalines;    
    table_name   col1   col2
    ----------   ----   ----
    Table_1       C1      C2
    Table_2       D1      D2
    Table_x       xx      yy
;run;



%InsertFromAllTables();

答案 5 :(得分:0)

我要把它分成另一个答案,因为它与我原来的想法完全不同。

我首先假设这是一个数据错误。通过执行以下操作进行故障排除: 1.使用前5000行。如果成功,则仅使用第二个5000行(firstobs = 5001)。如果两者都没有失败,那么它不是数据错误;如果其中一个或两个都失败,则可能是数据错误。 2.然后执行二叉树搜索算法。说第一个5000失败了。然后尝试第一个2500.如果失败然后尝试第一个1250.继续直到找到通过的东西。然后尝试通过的最后一个的另一半(例如,625通过;所以尝试626-1250)。

继续拆分,直到你可以检查一小组数据(一行,五行,最适合你查看数据的能力,特别是根据内部联接创建的行数)。查看行,看看是否有任何违规行为。

当然,如果你达到一个特定的大小(比如说625),并且发现从1到10000的所有625集合都没有通过,只是当它们组合成更大的集合时,你再次可能没有数据错误 - 但我会我想你可能会这么做,特别是考虑到拉里发布的链接。

如果您想要更快的解决方案,请考虑在DatasetA和TableA / B中执行相关变量的频率。看看其中一行中的任何内容是否属于非法或异常。例如,如果您看到一个不可能的日期,或者一个没有意义的负数,那么可能是错误的。

最后,这个插入行的系统是什么?我希望不是SAS(因为有许多更好的SAS-sy解决方案)。根据系统的不同,您可能违反了该系统的规则(如Larry的链接),或者您可能违反了表约束或SAS没有特殊错误消息的其他内容,但仍然违反了某些规则。无论如何,短语“域错误”可以这样解释。

答案 6 :(得分:0)

如果您拥有最新版本的SAS(版本9.3维护2),则可以尝试使用DOSUBL语句。它允许您在DATA步骤中运行任何SAS语句集合,只要这些语句代表“完整”步骤即可。即:全局语句,使用RUN的DATA步骤;使用RUN / QUIT的PROC步骤。

它被标记为实验,但this SAS Global Forum 2012 paper中提供了基本文档和示例。

注意:尽管DOSUBL最初是SAS 9.3中的有效语法,但我的经验是它使用SAS 9.3M2可以更好地工作。