拡張テーブルのフィールドの更新

[OS]ALL
[リリース] 6.07, 6.08, 6.09, 6.10
[キーワード] af, scl, extend, table, putrow, fetchobs, noset, option, getrow, update,function, set, ddv

[質問]

SASデータセットの内容を表示・更新する拡張テーブルを作成していますが、拡張テーブルのフィールドの更新がうまくできません。
どのようにしたらよいでしょうか。

[回答]

拡張テーブルでは、新たにテーブルを表示するときやスクロールするときに、テーブルの各行ごとにGETROWセクションが実行されます。
テーブルのフィールドを書き換えてスクロールなどの操作を行うと、デフォルトでは変更が行われた行だけに対してPUTROWセクションが実行されます。
変更を加えたある行に対してPUTROWセクションが実行されるとき、データセットデータベクトル(DDV)の内容は、一般的に直前のGETROWセクションで最後に読み込んだオブザベーションになります(GETROW以外で同じデータセットを読み込むプログラムの場合はもっと複雑になります) 。
つまり、DDVに入っているオブザベーションは、PUTROWで処理中の行のものとは限りません。
この状態でUPDATE関数を実行すると、期待したものとは異なる結果が、データセットに書き込まれてしまいます。

更新内容が正しくデータセットに書き込まれるようにするには、PUTROWセクションで処理中の行に対応するオブザベーションを一度DDVに読み込む必要があります。
DDVと拡張テーブルの各フィールドの値の同期をとるためにデータセットに対してSETルーチンを使用してある場合、通常のFETCHOBS関数は、読み込んだ値にもとづいてフィールドの値も元に戻してしまいます。したがって、一時的にSETルーチンの効果を取り消して読み込むために、NOSETオプションを指定したFETCHOBS関数を使う必要があります。

  PUTROW:
    rc=fetchobs(dsid,_currow_,'NOSET');
    if rc=0 then rc=update(dsid);
  return;