0

ユーザー入力を変数に取得し、それをカーソルに使用したいと考えています。このユーザー入力は、使用するデータベースを示します。

--source source 
source varchar2(100) := &SOURCE_ATS_USER_SCHEMA;
CURSOR cur_list is
    select ID from source.WEB_FE;

上記のコードを DECLARE ブロックで使用します。これが実行されると、プロンプトがユーザー入力を求めます。「ONE」と入力すると、「識別子ONEを宣言する必要があります」というエラーが表示され、ONE.WEB_FEテーブルが存在しても「テーブルまたはビューが存在しません」と表示されます。

では、ユーザー入力としてスキーマ名を取得し、それをカーソルで使用するにはどうすればよいでしょうか?

ありがとう

4

2 に答える 2

1

select on所有していないテーブルをクエリする権限があると仮定します。クエリの句でスキーマ修飾子を変更できるようにするにfromは、動的 SQL を使用する必要があります。例えば:

HR@XE> edit
Wrote file afiedt.buf

  1  declare
  2   c sys_refcursor;
  3   l_emp_name varchar2(11);
  4  begin
  5    open c for 'select first_name from ' || '&schema_name' || '.employees where rownum <= 10';
  6    loop
  7      fetch c into l_emp_name;
  8      exit when c%notfound;
  9      dbms_output.put_line(l_emp_name);
 10    end loop;
 11    close c;
 12* end;
HR@XE> /
Enter value for schema_name: hr
old   5:   open c for 'select first_name from ' || '&schema_name' || '.employees where rownum <= 10';
new   5:   open c for 'select first_name from ' || 'hr' || '.employees where rownum <= 10';

Ellen
Sundar
Mozhe
David
Hermann
Shelli
Amit
Elizabeth
Sarah
David

PL/SQL procedure successfully completed.

HR@XE>

また、静的SQLを使用し続け、発行することでスキーマを変更できます

alter session set current_schema = <<schema_name>>;

この場合、スキーマ名を指定してクエリを実行するテーブルを修飾する必要はありません。例えば。テーブルは両方のemployeeスキーマHRに存在しますが、NK異なるデータが含まれています:

HR@XE> select user from dual;

USER
------------------------------
HR

HR@XE> declare
  2    cursor c is
  3      select first_name
  4        from employees
  5       where rownum <= 7;
  6    l_emp_name varchar2(11);
  7  begin
  8     open c;
  9     loop
 10       fetch c into l_emp_name;
 11       exit when c%notfound;
 12       dbms_output.put_line(l_emp_name);
 13     end loop;
 14     close c;
 15  end;
 16  /

Ellen
Sundar
Mozhe
David
Hermann
Shelli
Amit

PL/SQL procedure successfully completed.

HR@XE> alter session set current_schema=NK;

Session altered.

HR@XE> declare
  2    cursor c is
  3      select first_name
  4        from employees
  5       where rownum <= 7;
  6    l_emp_name varchar2(11);
  7  begin
  8     open c;
  9     loop
 10       fetch c into l_emp_name;
 11       exit when c%notfound;
 12       dbms_output.put_line(l_emp_name);
 13     end loop;
 14     close c;
 15  end;
 16  /

Tom

PL/SQL procedure successfully completed.

HR@XE> alter session set current_schema=HR;

Session altered.

HR@XE>
于 2012-10-19T12:43:29.880 に答える
0

ここで 2 つの問題があります。メッセージは、identifier ONE must be declared置換変数を引用していないためです。持っている場合はset verify on、次のように表示されます。

Enter value for source_ats_user_schema: ONE
old   2: source varchar2(100) := &SOURCE_ATS_USER_SCHEMA;
new   2: source varchar2(100) := ONE;
source varchar2(100) := ONE;
                        *
ERROR at line 2:
ORA-06550: line 2, column 25:
PLS-00201: identifier 'SCOTT' must be declared
ORA-06550: line 2, column 8:
PL/SQL: Item ignored

'd 位置は、意味*がわからないことを示していONEます。ここでは文字列として扱いたいので、次のようにする必要があります。

source varchar2(100) := '&SOURCE_ATS_USER_SCHEMA';

...表示されます:

Enter value for source_ats_user_schema: ONE
old   2: source varchar2(100) := '&SOURCE_ATS_USER_SCHEMA';
new   2: source varchar2(100) := 'ONE';

...これは有効です。それが行く限り; まだ2番目のエラーがあるため、これは実際には役に立ちません:

    select ID from source.WEB_FE;
                          *
ERROR at line 4:
ORA-06550: line 4, column 27:
PL/SQL: ORA-00942: table or view does not exist
ORA-06550: line 4, column 5:
PL/SQL: SQL Statement ignored

エラーがsource.WEB_FEではなく ONE.WEB_FEを参照していることに注意してください。sourceは代用されていません。一般に、@NicholasKrasnov が彼の回答で示している方法の 1 つを使用する必要がありますが、実際にはこれを必要以上に複雑にしています。この特定のケースでは、宣言する必要はまったくありませんsource。次のようにするだけです。

CURSOR cur_list is
    select ID from &SOURCE_ATS_USER_SCHEMA..WEB_FE;

今言ったこととは反対に、ここでは置換変数を引用する必要はありませんが、テーブル名の前の.実数をターミネータとして扱うのを止めるために、明示的に で終了する必要があることに注意してください。(そうしない場合に何が起こるかを確認するため.に、余分なものなしで試してみてください)。.

実行するとプロンプトが表示され、検証出力は次のようになります。

Enter value for source_ats_user_schema: ONE
old   3:     select ID from &SOURCE_ATS_USER_SCHEMA..WEB_FE;
new   3:     select ID from ONE.WEB_FE;

ご覧のとおり、指定したスキーマでテーブルを探しています。これは依然として動的ですが、特別な SQL*Plus の方法です。

ただし、これらの方法では、SQL インジェクションの可能性を考慮する必要があります。

于 2012-10-19T15:56:59.040 に答える