0

別のデータベースユーザーを参照する必要がある場合があります。データベースのユーザー名を参照しながら、ビューにハードコーディングする必要があります。

SELECT * FROM  eg001t3.DUAL; // example.

ビューから動的に、またはデータベース設定に基づいて、そのdbユーザー(eg001t3)を参照する方法はありますか?

4

4 に答える 4

3

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

EXECUTE IMMEDIATE の例:

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 を使用することもできます。

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

示されているように、DBMS_ASSERT を使用して入力を検証できます。

于 2009-07-29T07:44:29.353 に答える
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
于 2009-07-29T10:10:59.937 に答える
1

(これを行う必要のあるアプリケーション環境に応じて)機能する可能性のある別のオプションは、名前空間を目的のスキーマに一時的に変更することです。

  1. セッションセットの変更current_schema=eg001t3;
  2. select * fromwhateverTableBelongsToEG001T3; -ここではスキーマ修飾子は必要ありません
  3. セッションセットを変更しますcurrent_schema=...-接続スキーマ名に戻ります

set current_schemaは、Oracle特権モデルをバイパスしません。他のスキーマの対象テーブルに対して少なくともSELECTが必要です。

于 2009-07-29T12:08:15.803 に答える
1

より洗練されたオプションがあるかもしれませんが、シノニムをその場で作成するか、動的 SQL / EXECUTE IMMEDIATE を使用することができます。

于 2009-07-29T07:43:45.283 に答える