2

テーブルにデータを入力するために、データ ステップ内で挿入ステートメントを実行しようとしています。コード ERROR: Domain error. の実行中に次のエラーが表示されます。ログには、このエラーに関する他の情報はありません。

私が実装しているサンプルコードは次のとおりです。

  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 は、クエリで使用しているデータセットの値です。

このエラーが発生する理由がわかりません。最初は、プロセッサの処理が多すぎるためではないかと考えていましたが、 sleep と wakeup を使用して待機しましたが、それでもエラーが発生します。また、常にこのエラーが発生するとは限りません。起こる時とそうでない時があります。

4

7 に答える 7

2

私はJoeのコードを実行している最中であり、問​​題はありません。これは、SAS9.2m3を搭載したWindows7であるため、環境が異なる場合があります。また、私はあなたのデータを持っていないので、あなたがしたことを複製することはできません。

コードを改善する可能性のあるものはたくさんありますが、エラーメッセージはSASの奥深くに問題があることを示しています。私は一般的に、SASと呼ばれるブラックボックスで何が起こっているのかを推測するよりも、SASTechサポートに確認する方が効率的だと思います。これに関するチケットを提出してください。

Oracle固有の問題を指摘しているSASサポートサイトで、このエラーメッセージを1つ参照しました。http://support.sas.com/kb/14/873.html

于 2012-10-18T20:50:57.097 に答える
1

まず、「PROCSQL;」を削除してみます。および「QUIT;」繰り返しのCALLEXECUTEから、それぞれ1回だけ実行します-IF N =1を使用します。PROC SQLを実行するには、LAST変数を使用してQUITを呼び出すタイミングを決定するか、データステップから除外してQUITを書き込むことができます。実行後; データステップの、それが適切な場所で実行されるように。SQL環境を繰り返し呼び出すと、問題自体が発生している可能性があります。

別の可能な解決策は、CALL EXECUTEを使用する代わりに、これらすべてをテキストファイルに書き込んでから、そのテキストファイルを%includeすることです。繰り返しますが、%includeはPROC SQLとQUITを含まない部分であり、%includeはPROCSQLブロック内にあります。ここでCALLEXECUTEに特に問題がある場合、これは機能に違いはなく、それを回避します。正直なところ、この方法の方が好きです。a)実際に行っていることに近い(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;
于 2012-10-17T06:44:43.507 に答える
0

SASの最新バージョン(バージョン9.3 Maint 2)を使用している場合は、DOSUBLステートメントを試してみてください。これらのステートメントが「完了」ステップを表す限り、DATAステップ内からSASステートメントのコレクションを実行できます。つまり、グローバルステートメント、RUNを使用したDATAステップ、RUN/QUITを使用したPROCステップです。

実験的としてマークされていますが、基本的なドキュメントと例は、このSASグローバルフォーラム2012のペーパーで入手できます。

注:DOSUBLは最初はSAS 9.3で有効な構文でしたが、私の経験では、SAS9.3M2ではるかにうまく機能します。

于 2012-10-19T18:12:37.857 に答える
0

のスケーリングの問題が原因であるというのは正しいと思いますcall execute。制限は、使用可能なメモリの量、命令キューの制限 (私はそれを作成しました) など、さまざまなことによって決定できます。

この場合の良い方法は、dataset set ステートメントでfirstobsandオプションを使用して、1000 回のバッチで実行される呼び出しを処理することです。obs

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

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

そして、必要に応じて上記のコードをマクロ化します...

于 2012-10-16T23:49:59.000 に答える
0

当初の考えとはまったく異なるため、これを別の回答に分割します。

まず、これはデータ エラーであると想定します。以下を実行してトラブルシューティングを行います。 1. 最初の 5000 行を使用します。成功した場合は、2 番目の 5000 行 (firstobs=5001) のみを使用します。どちらも失敗しない場合、それはデータ エラーではありません。1 つまたは両方が失敗した場合は、データ エラーである可能性があります。2. 次に、二分木検索のようなアルゴリズムを実行します。最初の 5000 が失敗したとします。次に、最初の 2500 を試します。それが失敗した場合は、最初の 1250 を試します。合格するものが見つかるまで続けます。次に、最後に合格したものの残りの半分を試します (たとえば、625 が合格したので、626-1250 を試します)。

検査できる小さなデータ セットが得られるまで、半分に分割し続けます (1 行、5 行、特に内部結合によって作成される行数に基づいて、データを表示する能力に最適なもの)。行を見て、違法の可能性があるものがないか確認します。

もちろん、特定のサイズ (たとえば 625) に達し、1 から 10000 までの 625 のすべてのセットが合格することがわかった場合、より大きなセットに結合された場合ではなく、再びデータ エラーが発生しない可能性がありますが、可能性が高いと思います特にラリーが投稿したリンクを考えると、あなたはそうします。

より高速なソリューションが必要な場合は、DatasetA と TableA/B の両方で関連する変数の度数を実行することを検討してください。これらの行の 1 つに、おそらく違法または異常なものがないかどうかを確認します。たとえば、不可能な日付や、意味をなさない負の数が表示された場合は、おそらく問題があります。

最後に、行を挿入するシステムは何ですか? SASではないことを願っています(より良いSAS-syソリューションがたくさんあるため)。システムによっては、そのシステムのルールの 1 つに違反している可能性があります (Larry のリンクのように)、またはテーブルの制約に違反している可能性や、SAS に特別なエラー メッセージがないにもかかわらず、いくつかのルールに違反している可能性があります。いずれにせよ、ドメイン エラーというフレーズはそのように解釈できます。

于 2012-10-18T21:36:34.470 に答える
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();
于 2012-10-17T21:11:48.640 に答える
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ここ) と外部ファイルの行サイズ (デフォルトでは 256) に注意してください。

于 2012-10-17T16:04:28.763 に答える