技術ブログ
Oracle Database 12cから、ビューへ発行されたSELECT文を再帰的に展開する機能が追加されました。 (実は昔からあったそうですが・・・後述)
例を用いて説明するのが理解がはやいでしょう。テーブルbase に対してビューv1を、ビューv1に対してビューv2を定義します。
SQL> create table base (i number, c varchar(80)); 表が作成されました。 SQL> insert into base values(1, 'AAA'); 1行が作成されました。 SQL> insert into base values(1, 'AAC'); 1行が作成されました。 SQL> insert into base values(2, 'BBB'); 1行が作成されました。 SQL> commit; コミットが完了しました。 SQL> SQL> create view v1 as select i,c from base WHERE i = 1; ビューが作成されました。 SQL> create view v2 as select i,c from v1 WHERE c = 'AAA'; ビューが作成されました。 SQL> SELECT * FROM v2; I C ---------- -------------------------------------------------------------------------------- 1 AAA
テーブルbase ←ビューv1 ← ビューv2の関係になっており、ビューv2に対するSELECTは当然正常に実行できます。このSELECT文をDBMS_UTILITY.EXPAND_SQL_TEXTでベースとなるテーブルのSELECT文に展開してみます。展開処理は再帰的に実行されるので、ビューが多段でもOKです。
SQL> set long 2000000000 SQL> set pagesize 0 SQL> set serveroutput on SQL> declare 2 original_sql clob :='SELECT * FROM v2'; 3 expanded_sql clob := empty_clob(); 4 begin 5 dbms_utility.expand_sql_text(original_sql,expanded_sql); 6 dbms_output.put_line(expanded_sql); 7 end; 8 / SELECT "A1"."I" "I","A1"."C" "C" FROM (SELECT "A2"."I" "I","A2"."C" "C" FROM (SELECT "A3"."I" "I","A3"."C" "C" FROM RYWATABE."BASE" "A3" WHERE "A3"."I"=1) "A2" WHERE "A2"."C"='AAA') "A1" PL/SQLプロシージャが正常に完了しました。
では、この機能は実は過去のバージョンより存在していたという指摘があります。
されて、DBMS_SQL2.EXPAND_SQL_TEXTを使って同様の処理を・・・と思いましたが
SQL> declare 2 m_sql_in clob :='SELECT * FROM v2'; 3 m_sql_out clob := empty_clob(); 4 begin 5 dbms_sql2.expand_sql_text(m_sql_in,m_sql_out); 6 dbms_output.put_line(m_sql_out); 7 end; 8 / dbms_sql2.expand_sql_text(m_sql_in,m_sql_out); * 行5でエラーが発生しました。: ORA-06550: 行5、列5: PLS-00201: 識別子DBMS_SQL2.EXPAND_SQL_TEXTを宣言してください。 ORA-06550: 行5、列5: PL/SQL: Statement ignored SQL> desc dbms_sql2 ERROR: ORA-04043: オブジェクトdbms_sql2は存在しません。 SQL> desc sys.dbms_sql2 ERROR: ORA-04043: オブジェクトsys.dbms_sql2は存在しません。
12.1.0.1ではすでにDBMS_SQL2パッケージが削除されているようです。
11.2.0.3ではDBMS_SQL2パッケージがあり、DBMS_SQL2.EXPAND_SQL_TEXTで同様の処理が可能でした。 知らなかった・・・
SQL> SELECT * FROM V$VERSION; BANNER -------------------------------------------------------------------------------- Oracle Database 11g Enterprise Edition Release 11.2.0.3.0 - 64bit Production PL/SQL Release 11.2.0.3.0 - Production CORE 11.2.0.3.0 Production TNS for Linux: Version 11.2.0.3.0 - Production NLSRTL Version 11.2.0.3.0 - Production SQL> set long 2000000000 SQL> set pagesize 0 SQL> set serveroutput on SQL> declare 2 m_sql_in clob :='SELECT * FROM v2'; 3 m_sql_out clob := empty_clob(); 4 begin 5 dbms_sql2.expand_sql_text(m_sql_in,m_sql_out); 6 dbms_output.put_line(m_sql_out); 7 end; 8 / SELECT "A1"."I" "I","A1"."C" "C" FROM (SELECT "A2"."I" "I","A2"."C" "C" FROM (SELECT "A3"."I" "I","A3"."C" "C" FROM RYWATABE."BASE" "A3" WHERE "A3"."I"=1) "A2" WHERE "A2"."C"='AAA') "A1" PL/SQLプロシージャが正常に完了しました。