2009-07-29 9 views
0

私は別のデータベースユーザーを参照する必要がある場合があります。私はそれを参照しながら、ビューでデータベースのユーザー名をハードコードする必要があります。他のデータベースユーザを動的に参照する方法は?

SELECT * FROM eg001t3.DUAL; // example. 

ビューを動的またはデータベースのセットアップに基づいてからそのDBユーザー(eg001t3)を参照する方法はありますか?

+0

あなたはそのデータを表示する必要がありますか、それともDBでそれ以上のことをしますか? – jva

+0

私は、表示するために別のデータベースユーザーからデータを取得する必要があります。 – Ahmed

答えて

1

さらに高度なオプションがありますが、その場で同義語を作成するか、動的SQL/EXECUTE IMMEDIATEを使用することができます。

3

pl/sqlでは、EXECUTE IMMEDIATEまたはDBMS_SQLを使用してオブジェクトを動的に参照します。

EXECUTE IMMEDIATEとExemple:

SQL> VARIABLE dyn_user VARCHAR2(30); 
SQL> EXEC :dyn_user := 'SYS'; 

PL/SQL procedure successfully completed 
dyn_user 
--------- 
SYS 
SQL> DECLARE 
    2  ln NUMBER; 
    3 BEGIN 
    4  EXECUTE IMMEDIATE 'SELECT 1 
    5       FROM ' || dbms_assert.schema_name(:dyn_user) 
    6         || '.DUAL' 
    7  INTO ln; 
    8  dbms_output.put_line(ln); 
    9 END; 
10/

1 

PL/SQL procedure successfully completed 

あなたはまた、動的に構築されたREF CURSORを使用することができます:あなたはあなたの入力を検証するためにDBMS_ASSERTを使用することができます示すように

SQL> DECLARE 
    2  lc SYS_REFCURSOR; 
    3  ln NUMBER; 
    4 BEGIN 
    5  OPEN lc FOR 'SELECT 1 
    6     FROM ' || dbms_assert.schema_name(:dyn_user) || '.DUAL 
    7     CONNECT BY level <= 2'; 
    8  LOOP 
    9  FETCH lc 
10   INTO ln; 
11  EXIT WHEN lc%NOTFOUND; 
12  dbms_output.put_line(ln); 
13  END LOOP; 
14  CLOSE lc; 
15 END; 
16/

1 
1 

を。

+0

ビューで使用することは可能ですか? – Ahmed

+0

@Ahmed:いいえ、それはビューでは機能しません。ビューは、コンパイル時に参照されているオブジェクトを知る必要があります。 –

+0

@Vincent:これを表示する方法はありますか? – Ahmed

2

jvaで提案されている別の方法を示す新しい回答を追加します。すべての表は共通の構造を共有する必要があります(コンパイル時にOracleがビューの列のデータ型を認識できるようにする必要があります)。

セットアップ:

-- create 2 schemas 
CREATE USER u1 IDENTIFIED BY u1; 
CREATE USER u2 IDENTIFIED BY u2; 
GRANT RESOURCE TO u1; 
GRANT RESOURCE TO u2; 

-- one table in each schema 
CREATE TABLE u1.t AS 
    SELECT 2 * ROWNUM ID, 'foo' DATA FROM dual CONNECT BY LEVEL <= 5; 
CREATE TABLE u2.t AS 
    SELECT 2 * ROWNUM - 1 ID, 'bar' DATA FROM dual CONNECT BY LEVEL <= 5; 
GRANT SELECT ON u2.t TO u1; 

-- the common structure 
CREATE TYPE u1.t_row AS OBJECT (ID NUMBER, DATA VARCHAR2(3)); 
/
CREATE TYPE u1.t_row_list AS TABLE OF u1.t_row; 
/

CREATE OR REPLACE PACKAGE u1.test_pck IS 
    schema_name VARCHAR2(30) := 'U1'; 
    FUNCTION select_t RETURN u1.t_row_list PIPELINED; 
END test_pck; 
/

--Definition of the pipelined function and the view: 
CREATE OR REPLACE PACKAGE BODY u1.test_pck IS 

    FUNCTION select_t RETURN u1.t_row_list PIPELINED IS 
     l_rc  SYS_REFCURSOR; 
     l_id  NUMBER; 
     l_data VARCHAR2(3); 
    BEGIN 
     OPEN l_rc FOR 'SELECT id, data 
         FROM ' || dbms_assert.schema_name(schema_name) || '.t'; 
     LOOP 
     FETCH l_rc 
      INTO l_id, l_data; 
     EXIT WHEN l_rc%NOTFOUND; 
     PIPE ROW (u1.t_row(l_id, l_data)); 
     END LOOP; 
     CLOSE l_rc; 
    END select_t; 

END test_pck; 
/

CREATE OR REPLACE VIEW u1.v AS 
SELECT ID, DATA 
    FROM TABLE(u1.test_pck.select_t); 

あなたは、スキーマ名を含むパッケージでグローバル変数を定義し、ビューを照会します:あなたのために働くかもしれない

SQL> EXEC u1.test_pck.schema_name := 'U1'; 

PL/SQL procedure successfully completed 
SQL> SELECT * FROM u1.v; 

     ID DATA 
---------- ---- 
     2 foo 
     4 foo 
     6 foo 
     8 foo 
     10 foo 
SQL> EXEC u1.test_pck.schema_name := 'U2'; 

PL/SQL procedure successfully completed 
SQL> SELECT * FROM u1.v; 

     ID DATA 
---------- ---- 
     1 bar 
     3 bar 
     5 bar 
     7 bar 
     9 bar 
1

別のオプション(に応じてあなたがこれを行う必要があるアプリケーション環境)は、あなたの名前空間を関心のあるスキーマに一時的に変更することです:

  1. セッションを変更するcurrent_schema = eg001t3;
  2. select * from whateverTableBelongsToEG001T3; - ここで必要なしスキーマ修飾子
  3. ALTER SESSIONセットCURRENT_SCHEMA = ... - あなたの接続スキーマ名にバック

セットCURRENT_SCHEMAは、どのような方法でのOracle権限モデルをバイパスしません - あなたはまだよ他のスキーマの関心のあるテーブルで少なくともSELECTが必要です。

+0

によって提案された方法を示す別の回答を追加しました。これは機能し、私の考えよりはるかに優れています。 – jva

関連する問題