【问题标题】:get schema name as a user input and use it in a cursor获取模式名称作为用户输入并在游标中使用它
【发布时间】:2012-10-09 23:20:51
【问题描述】:

我想获取用户对变量的输入并将其用于游标。此用户输入说明要使用哪个数据库。

--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 表存在,但它说“表或视图不存在”。

那么如何获取模式名称作为用户输入并在游标中使用呢?

感谢

【问题讨论】:

    标签: oracle stored-procedures cursor sqlplus


    【解决方案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>
    

    【讨论】:

    • 感谢您的支持。但是我必须引用来自不同模式的四个表,并且我无法提示用户输入相同的四次。正如亚历克斯普尔所说, source varchar2(100) := '&SOURCE_ATS_USER_SCHEMA';为我工作。
    【解决方案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';
    

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

        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;
    

    请注意,与我刚才所说的相反,这里您不需要引用替换变量,但您需要用. 显式终止它,以阻止它在表名之前处理真正的.作为终结者。 (试试不带额外的. 看看如果不这样做会发生什么)。

    运行时会提示,验证输出如下:

    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 注入的可能性。

    【讨论】:

    • 谢谢。源 varchar2(100) := '&SOURCE_ATS_USER_SCHEMA';成功了。
    猜你喜欢
    • 1970-01-01
    • 2021-06-30
    • 2013-10-06
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-11-04
    • 1970-01-01
    相关资源
    最近更新 更多