2017-08-30 5 views
1

テーブルに対してSELECTクエリを実行しようとする簡単な匿名プロシージャを作成しようとしています。問題はこのテーブルの古いバージョンにあり、存在しないカラムはほとんどなく、これらの新しいカラムは新しいバージョンのテーブル構造に導入されました。Oracle PL/SQL:古いバージョンのテーブルには条件付きで列を使用する方法

私はこの新しい列が存在するかどうかを確認しており、唯一の列が存在する場合は条件付きでSELECTクエリを使用しています。しかし、スタティックコンパイルが原因であると思われます。

PL/SQL: ORA-00904: "ERRORTYPE": invalid identifier 

どうすれば対処できますか?以下はサンプル手順です

SET SERVEROUTPUT ON; 
DECLARE 
    errorType_column_exists number := 0; 
BEGIN 
    SELECT COUNT(*) INTO errorType_column_exists 
    FROM ALL_TAB_COLS 
    WHERE owner = 'DEV' 
    AND table_name = 'Table1' 
    AND column_name = 'ERRORTYPE'; 
    IF (errorType_column_exists = 1) THEN 
     FOR r_row IN (SELECT ErrorMsg 
       FROM DEV.Table1 
       WHERE (ErrorType != 'Missing' OR ErrorType IS NULL) 
       AND ROWNUM <= 100) 
    LOOP 
     DBMS_OUTPUT.PUT_LINE(r_row.ErrorMsg); 
     END LOOP; 
    END IF; 
END; 
/
+0

あなたは動的SQLを使用することができます...単純な '即時実行'は問題を解決するでしょう – smnbbrv

+0

いくつかの文脈をしてください。 「このテーブルの古いバージョン」と言うと、正確に何が起きていますか?あなたは様々なヴィンテージのスキーマを持つ複数のデータベースを持っていますか?あなたはすべての構成で実行される1つのコードを書こうとしていますか? – APC

+0

こんにちは、なぜ手順はバージョン間で共通ですか?それぞれのバージョンで異なるプロシージャを実装する必要があります。各手順でそのバージョンの正しい列が使用されるようにします。 – Ramki

答えて

0

実行する前にコードをコンパイルする必要があります。ループ内のコードは、TABLE1にerror_typeという列があるスキーマでのみコンパイルされます。

スキーマのすべてのバージョンに対してコンパイルする匿名ブロックを作成する唯一の方法は、動的SQLを使用することです。

SET SERVEROUTPUT ON; 
DECLARE 
    errorType_column_exists number := 0; 
    Lnt sys.dbms_debug_vc2coll; 
    BEGIN 
     SELECT COUNT(*) INTO errorType_column_exists 
    FROM ALL_TAB_COLS 
    WHERE owner = 'DEV' 
    AND table_name = 'Table1' 
    AND column_name = 'ERRORTYPE'; 
    IF (errorType_column_exists = 1) 
    THEN 
      execute Immediate 'SELECT ErrorMsg FROM DEV.Table1 WHERE (ErrorType != ''Missing'' OR ErrorType IS NULL) AND ROWNUM <= 100' 
      bulk collect into lnt; 
      for idx in 1..lnt.count() 
      LOOP 
       DBMS_OUTPUT.PUT_LINE(lnt(idx)); 
    END LOOP; 
    END IF; 
END; 
/
+0

申し訳ありませんレイアウトは非常にショーンですが、SEアプリケーションのコードブロックを書式設定するのはTeh Suckです! – APC

+1

これは本当に助けてくれてありがとう! – Karesh

+0

"bulk collect into lnt;"という行に気づいたthrows - ORA-06502:PL/SQL:数値または値のエラーです。これを守る方法はありますか? 実際に私は以下のように変数宣言を変更しました: lnt sys.odcivarchar2list; – Karesh

2

これを行うには、公式のOracleの方法は、条件付きコンパイルを使用することです:だからあなたはあなたが扱っているスキーマのバージョンに応じてPL/SQLコンパイラフラグを設定する必要があります

alter session set PLSQL_CCFlags = 'schema_version:2' 

DECLARE 
    errorType_column_exists number := 0; 
BEGIN 

    FOR r_row IN (SELECT ErrorMsg 
      FROM DEV.Table1 
      $if $$schema_version >= 2 $then 
      WHERE (ErrorType != 'Missing' OR ErrorType IS NULL) 
      $else 
      WHERE 1=1 
      $end 
      AND ROWNUM <= 100) 
    LOOP 
     DBMS_OUTPUT.PUT_LINE(r_row.ErrorMsg); 
    END LOOP; 
END; 

を。

+0

私はCCを解決策として提案することを検討しましたが、それは匿名ブロックのために少しばかげています。この場合でも、列が存在しない場合は処理を行う必要はないと思われるので、実装が正しいかどうかはわかりません。しかし、このアプローチは他のわずかに異なるユースケースに適しています。 – APC

関連する問題