2014年11月26日水曜日

定数を配列の要素とした場合の事象

現場でSASプログラム開発中にハマった事象を紹介します。
定数を配列の要素とした場合に発生します。


複数の変数に対して同じ処理を行う場合にARRAYステートメントで配列を定義し、DOステートメントで繰り返し処理をする場面がよくあります。
多くの場合では①のように変数を配列の要素として定義するのではないでしょうか。


data test1 ;
  array yyyymm(6) yyyymm1 yyyymm2 yyyymm3 yyyymm4 yyyymm5 yyyymm6 ;
  set test0 ;
  /* 日付変数を初期化 */
  do i = 1 to 6 ;
    yyyymm(i) = 0 ;
  end ;
run ;


しかし今回のプログラムでは②のようにマクロ変数で設定した定数を配列の要素として定義しました。


/* マクロ変数作成 */
%let yyyymm1 = 201404 ;
%let yyyymm2 = 201405 ;
%let yyyymm3 = 201406 ;
%let yyyymm4 = 201407 ;
%let yyyymm5 = 201408 ;
%let yyyymm6 = 201409 ;

/* データセット更新 */
data test1 ;
  set test0 ;
  array yyyymm(6)(&yyyymm1 &yyyymm2 &yyyymm3 &yyyymm4 &yyyymm5 &yyyymm6) ;
  tuki1 = yyyymm(1) ;
  tuki2 = yyyymm(2) ;
  tuki3 = yyyymm(3) ;
  tuki4 = yyyymm(4) ;
  tuki5 = yyyymm(5) ;
  tuki6 = yyyymm(6) ;
run ;

①ではSAS変数が配列の要素として定義されます。
しかし②では定数を配列の要素としています。変数の指定はされていませんがどうなるでしょうか?

この場合は配列名である「yyyymm」 に 「連番」を付与した変数が自動生成されます。
つまりyyyymm1~yyyymm6という変数が自動で作成されるのです。

たとえばデータセットtest0にyyyymm3という変数を元々持っている場合に
②を実行すると、データセットtest0の変数yyyymm3がARRAYに定数を定義したときに自動生成されたyyyymm3で上書きされてしまいます。
マクロ変数yyyymm3に設定している201406に更新されます。

現場で不具合が発生したときも、もともとのデータセットにyyyymm3という変数を持っていたところに、配列yyyymmの要素に定数をセットしたため変数yyyymm3が生成され想定していない更新が発生しました。

ARRAYに定数を設定したときに変数が自動生成されてもログにメッセージも出力されませんので、
ARRAYに定数を設定すると配列名+連番で変数が生成されることを認識していないと思わぬ更新がされることになります。

現場のメンバーも認識している人は少なかったので今回の事象を紹介させていただきました。
定数を配列の要素とする場合は注意しましょう。


ネイチャーインサイト サイトリニューアル&NIBLOGの引っ越し

ご連絡が遅くなりましたが、 ネイチャーインサイトの際とがリニューアルしました。 https://www.n-insight.co.jp/ それに伴い、NIBLOGも引っ越しすることになりました。 https://www.n-insight.co.jp/niblog/ ...