【问题标题】:Oracle - using synonym as variableOracle - 使用同义词作为变量
【发布时间】:2021-10-03 01:34:50
【问题描述】:

我需要在块中使用同义词作为变量。我有 2 个不同的模式,上面有相同的表,并且工作在模式之间切换,使一个处于活动状态。现在我想编写一个块来检查哪个模式使用 ALL_SYNONYMS 处于活动状态,并将结果用作查询的一部分。 示例如下:

DECLARE
  OWNER VARCHAR2(15);
BEGIN
  SELECT TABLE_OWNER
    INTO OWNER
    FROM ALL_SYNONYMS
   WHERE TABLE_NAME = 'MY_TABLE1';
  SELECT *
    FROM OWNER.MY_TABLE2 ;
END;

但是我得到 ORA-06550 表或视图不存在,当我运行查询本身时,我从 ALL_SYNONYMS 中输入值,它返回结果。

知道如何解决这个问题吗?

谢谢

【问题讨论】:

  • 在不了解更多信息的情况下,我会说“修复”的方法是修复您的设计 - 不断在两种模式之间切换,因为“活动”与“非活动”听起来像是设计失败第一个订单。
  • 您不能在 SQL 中使用“变量”对象名称,除非它是动态的。在您正在使用的版本的 pl/sql 手册中查找“立即执行”。
  • 如果提供的任何答案解决了您的问题,请接受。这样做有助于未来的提问者有同样的问题,并从未回答的列表中删除问题。如果两者都没有解决您的问题,那么它们的不足之处在哪里。

标签: oracle plsql oracle12c plsqldeveloper


【解决方案1】:

您正在尝试错误地使用症状。使用了同义词,因此您不需要知道哪个是活动的。根据documentation

同义词提供数据独立性和位置透明度。 同义词允许应用程序无需修改即可运行 无论哪个用户拥有表或视图,也不管 哪个数据库保存表或视图。

您只需使用同义词而不是对象本身。

create table evens( id integer generated always as identity
                  , val  integer 
                  ) ; 
                  
create table odds( id integer generated always as identity
                  , val  integer 
                  ) ; 
                  
insert all 
   when mod(val,2) = 0 then into evens(val)
   when mod(val,2) = 1 then into odds(val)
  select level val 
    from dual connect by level <= 10; 

-- create the synonym then use it in Select;     
create or replace synonym current_even_odd for evens;  

select * from current_even_odd;

-- now change the synonym, then run the EXACT same query.   
create or replace synonym current_even_odd for odds;  

select *  from current_even_odd;

在这种情况下,它不是完全没有修改,您需要更改同义词,但您似乎已经在尝试。

注意:您不能为模式创建同义词,但必须将其指向特定对象。

我为上述尝试了一个 dbfiddle,但它目前似乎有问题。

【讨论】:

    【解决方案2】:

    我同意 Belayer 的观点,即同义词应该在您的表上提供一个抽象层,并且您的过程不需要知道架构是什么。但是“表或视图不存在”错误可能是与特权和定义者权限与调用者权限相关的问题。

    要直接引用过程中的对象,过程的架构必须直接授予表。但是,即席查询只需要对对象具有特权的角色。这就是为什么 SQL 可以在您的 IDE 中工作但不能在过程中工作的原因。确保修改对象和切换同义词的代码将权限授予两个角色并直接授予架构。

    如果无法直接授予,您将需要修改过程以使用AUTHID CURRENT_USER 并更改 SQL 语句以使用动态 SQL - 这可能是一个巨大的痛苦。例如:

    create or replace procedure test_procedure authid current_user is
        v_count number;
    begin
        execute immediate
        q'[
            select count(*)
            from some_table
        ]'
        into v_count;
    end test_procedure;
    /
    

    如果您确实需要在模式之间手动切换,那么您可能需要考虑在过程中使用 execute immediate 'alter session set current_schema=schema1'; 之类的东西,并为所有查询使用动态 SQL。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2017-10-15
      • 1970-01-01
      • 1970-01-01
      • 2011-10-06
      • 2021-09-17
      • 2011-05-01
      • 2010-09-21
      • 2011-10-04
      相关资源
      最近更新 更多