3
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

ソートしていない内部テーブルをバイナリサーチしてはいけない

Posted at

表題のコーディングが原因でバグが発生しました。

バイナリサーチの仕組みを知っていれば当たり前の話なのですが、意識していないとついついやってしまいます。

VBAK(受注伝票ヘッダー)に次のようなデータが格納されているとします。
※本来であれば、主キーであるVBELNでソートされていると思いますが、例なので気にしないで下さい。

VBELN AUDAT AUART WAERK
101 2019/1/1 XXX USD
104 2019/1/1 XXX JPY
103 2019/1/1 XXX USD
102 2019/1/1 XXX EUR
105 2019/1/1 XXX JPY

以下のようなコーディングをすると、結果は"伝票が見つかりません(>_<)"となります。
(READ TABLEの検索が失敗します。)

* 受注伝票を全件内部テーブル(IT_VBAK)に格納
DATA: IT_VBAK TYPE STANDARD TABLE OF VBAK.    " 受注伝票ヘッダテーブル
      ST_VBAK LIKE LINE OF IT_VBAK. " 構造


SELECT * 
  INTO TABLE IT_VBAK
  FROM VBAK.


* 対象受注伝票をST_VBAKに格納
READ TABLE IT_VBAK
      INTO ST_VBAK
  WITH KEY VBELN = ‘104’  "伝票番号104の行をREADする
BINARY SEARCH.   "バイナリサーチする

IF SY-SUBRC = 0.

write:/ ‘伝票が見つかりました!'. 

ELSE.

write:/ ‘伝票が見つかりません(>_<)'.

ENDIF.

まあ当然ですね。

101, 104, 103, 102, 105をバイナリサーチで探すのですから。

とりあえず真ん中を見る。
→103か、違うな。じゃあ103と105の間を見るか。
→102か、違うな。"104"は無いっぽいな。諦めよう。

となるわけです。

上記の事象を回避するには、READ TABLEする前に検索キーで内部テーブルをソートしてあげましょう。

SELECT * 
  INTO TABLE IT_VBAK 
  FROM VBAK.

* 内部テーブルのソート
SORT IT_VBAK  ASCENDING BY VBELN.

* 対象受注伝票をWA_TABLEに格納
READ TABLE IT_VBAK 
      INTO ST_VBAK 
  WITH KEY VBELN = ‘104’  "伝票番号104の行をREADする
BINARY SEARCH.   "バイナリサーチする

あるいは、最初っから内部テーブルを宣言するときにSORTテーブルにするのも手です。

* 受注伝票を全件内部テーブル(IT_TABLE)に格納
DATA: IT_VBAK TYPE SORTED TABLE OF VBAK    " 受注伝票ヘッダテーブル
                    WITH UNIQUE KEY VBELN.  " 伝票番号でソート
      ST_VBAK LIKE LINE OF IT_VBAK. " 構造


SELECT * 
  INTO TABLE IT_VBAK
  FROM VBAK.


READ TABLE IT_VBAK
      INTO ST_VBAK
  WITH KEY VBELN = ‘104’  "伝票番号104の行をREADする
BINARY SEARCH.   "バイナリサーチする

てか、有効化するときに警告出してくれたらいいのに

3
1
2

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
3
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?