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表存在于两种模式中HRNK但包含不同的数据:

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

你这里有两个问题。该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';

...这是有效的。就目前而言;这实际上对您没有帮助,因为您仍然有第二个错误:

    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_FEsource没有被替换。通常,您需要使用@NicholasKrasnov 在他的回答中显示的一种方法,但实际上您使这比需要的更复杂;在这种特定情况下,您根本不需要声明source,您可以这样做:

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

请注意,与我刚才所说的相反,这里您不需要引用替换变量,但您确实需要用 a 显式终止它.,以阻止它将.表名之前的实数视为终止符。(试一试没有额外.的,看看如果你不这样做会发生什么)。

当您运行它时,它会提示并且验证输出将如下所示:

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 回答