« 基本に戻ろう: アンチジョインとセミジョイン
Oracle Database 11g Release 1 ダウンロード開始! »


7月

9

OracleでANSI SQL結合構文が正常に動作しないケース

参照元:When ANSI SQL Join Syntax Does Not Work in Oracle < Eddie Awad’s Blog

— beginning of translation —

私はOracleのANSI SQL構文に自信をなくしてしまいました。Ericは、基本に戻ろう: アンチジョインとセミジョインのコメントで、次のような注意を促してくれました。

ウェアハウス用に非正規化されているデータのように、多くの表から
結果を取得し、しかもその結合表の列数の合計が1050を超える場合、
常にORA-01445が発生します。この現象は9iから10g2で発生します。
そして、本来ならばOracleでANSI構文を使いたいところなのですが、
しばしばこの現象に出くわすため、少数の表を問合せる以外では
ANSI構文を使いません。

そして、この現象は私の環境でも発生しました。以下に示す2つの問合せは、どちらもOracle E-Business Suite (11.5.10)の標準的な表を使用しており、最初の例がANSI構文、2番目の例がOracle構文を使用しているという点以外は同一の文です。そして、お分かりのように、ANSI構文を使った結合文のほうは、次のようなエラーで無残にも失敗してしまいました:

ORA-01445: キー保存表なしに結合ビューからROWID を選択できません。

これは私にはバグのように見えます。面白いことに、問合せ文のSELECT NULLという箇所をSELECT COUNT(*)に変えると正常に動きます。

APPS@sigma> select * from v$version;BANNER

----------------------------------------------------------------

Oracle Database 10g Enterprise Edition Release 10.1.0.5.0 - Prod

PL/SQL Release 10.1.0.5.0 - Production

CORE    10.1.0.5.0      Production

TNS for Linux: Version 10.1.0.5.0 - Production

NLSRTL Version 10.1.0.5.0 - Production

APPS@sigma> SELECT NULL

  2    FROM oe_order_headers_all header INNER JOIN oe_order_lines_all line

  3         ON header.header_id = line.header_id

  4         INNER JOIN ra_customers cust ON header.sold_to_org_id = cust.customer_id

  5         INNER JOIN mtl_system_items_b item

  6         ON item.inventory_item_id = line.inventory_item_id

  7       AND item.organization_id = line.ship_from_org_id

  8         INNER JOIN org_organization_definitions org

  9         ON org.organization_id = line.ship_from_org_id

 10         LEFT OUTER JOIN ra_salesreps_all salesrep

 11         ON salesrep.salesrep_id = header.salesrep_id

 12       AND salesrep.org_id = header.org_id

 13         LEFT OUTER JOIN hr_locations_all sales_loc

 14         ON sales_loc.location_id = salesrep.attribute1

 15   WHERE header.orig_sys_document_ref = 'OE_ORDER_HEADERS_ALL74846'

 16     AND header.order_source_id = 0;

LEFT OUTER JOIN hr_locations_all sales_loc

                       *

ERROR at line 13:

ORA-01445: cannot select ROWID from, or sample, a join view without a

key-preserved table

今度は従来のOracle構文を使った正しい書き方です:

APPS@sigma> SELECT NULL

  2    FROM oe_order_headers_all header,

  3         oe_order_lines_all line,

  4         ra_customers cust,

  5         mtl_system_items_b item,

  6         org_organization_definitions org,

  7         ra_salesreps_all salesrep,

  8         hr_locations_all sales_loc

  9   WHERE header.header_id = line.header_id

 10     AND header.sold_to_org_id = cust.customer_id

 11     AND item.inventory_item_id = line.inventory_item_id

 12     AND item.organization_id = line.ship_from_org_id

 13     AND org.organization_id = line.ship_from_org_id

 14     AND salesrep.salesrep_id(+) = header.salesrep_id

 15     AND salesrep.org_id(+) = header.org_id

 16     AND sales_loc.location_id(+) = salesrep.attribute1

 17     AND header.orig_sys_document_ref = 'OE_ORDER_HEADERS_ALL74846'

 18     AND header.order_source_id = 0;N

-

2 rows selected.

さらに興味深いことに、ORA-01445エラーについて、Oracle Databaseエラー・メッセージ 10g リリース1(10.1)および、リリース2(10.2)のどこにも言及されていないのです。しかしながら、以下のサイトで参照することができました:

* Andrew Channels Dexter Pinion: ORA-01445
* Oracle-l: limit on number of tables in join
* OraFAQ Forum: Urgent-ORA-01445
* Outer join - same query, different results
* Oracle bug no. 5967612 on Metalink

— end of translation —

Leave a Reply

Comment