4

我正在尝试编写一个表触发器来查询触发器所在的架构之外的另一个表。这可能吗?似乎我在架构中查询表没有问题,但我得到:

Error: ORA-00942: table or view does not exist

尝试查询我的架构之外的表时。

编辑

对于第一次没有提供尽可能多的信息,我深表歉意。我的印象是这个问题更简单。

我正在尝试在表上创建一个触发器,该触发器根据某些数据的存在来更改新插入的行上的某些字段,这些数据可能存在于或可能不在另一个模式中的表中。

我用来创建触发器的用户帐户确实有权独立运行查询。事实上,我已经让我的触发器打印了我正在尝试运行的查询,并且能够成功地自行运行它。

我还应该注意,我正在使用 EXECUTE IMMEDIATE 语句动态构建查询。这是一个例子:

CREATE OR REPLACE TRIGGER MAIN_SCHEMA.EVENTS
BEFORE INSERT
ON MAIN_SCHEMA.EVENTS REFERENCING OLD AS OLD NEW AS NEW
FOR EACH ROW
DECLARE 
    rtn_count NUMBER := 0;
    table_name VARCHAR2(17) := :NEW.SOME_FIELD;
    key_field VARCHAR2(20) := :NEW.ANOTHER_FIELD;
BEGIN
    CASE
        WHEN (key_field = 'condition_a') THEN
            EXECUTE IMMEDIATE 'select count(*) from OTHER_SCHEMA_A.'||table_name||' where KEY_FIELD='''||key_field||'''' INTO rtn_count;
        WHEN (key_field = 'condition_b') THEN
            EXECUTE IMMEDIATE 'select count(*) from OTHER_SCHEMA_B.'||table_name||' where KEY_FIELD='''||key_field||'''' INTO rtn_count;
        WHEN (key_field = 'condition_c') THEN
            EXECUTE IMMEDIATE 'select count(*) from OTHER_SCHEMA_C.'||table_name||' where KEY_FIELD='''||key_field||'''' INTO rtn_count;
    END CASE;

    IF (rtn_count > 0) THEN
        -- change some fields that are to be inserted
    END IF; 
END;

触发器接缝在 EXECUTE IMMEDIATE 上失败,并出现前面提到的错误。

编辑

我做了更多的研究,我可以提供更多的澄清。

我用来创建此触发器的用户帐户不是 MAIN_SCHEMA 或任何 OTHER_SCHEMA_Xs。我正在使用的帐户(ME)通过架构用户本身获得了对相关表的权限。例如(USER_TAB_PRIVS):

GRANTOR        GRANTEE TABLE_SCHEMA    TABLE_NAME PRIVILEGE GRANTABLE HIERARCHY
MAIN_SCHEMA    ME       MAIN_SCHEMA    EVENTS     DELETE    NO        NO
MAIN_SCHEMA    ME       MAIN_SCHEMA    EVENTS     INSERT    NO        NO
MAIN_SCHEMA    ME       MAIN_SCHEMA    EVENTS     SELECT    NO        NO
MAIN_SCHEMA    ME       MAIN_SCHEMA    EVENTS     UPDATE    NO        NO
OTHER_SCHEMA_X ME       OTHER_SCHEMA_X TARGET_TBL SELECT    NO          NO

我有以下系统权限(USER_SYS_PRIVS):

USERNAME   PRIVILEGE            ADMIN_OPTION
ME         ALTER ANY TRIGGER    NO
ME         CREATE ANY TRIGGER   NO
ME         UNLIMITED TABLESPACE NO

这是我在 Oracle 文档中找到的:

要在另一个用户的架构中创建触发器,或者从您的架构中的触发器引用另一个架构中的表,您必须具有 CREATE ANY TRIGGER 系统权限。使用此权限,触发器可以在任何模式中创建,并且可以与任何用户的表相关联。此外,创建触发器的用户还必须对引用的过程、函数或包具有 EXECUTE 权限。

此处:Oracle 文档

所以在我看来这应该可以工作,但我不确定它在文档中所指的“执行特权”。

4

3 回答 3

5

您所体验的是 Oracle 安全模型的一个特性。使用模式的全部意义在于控制对数据的访问。我的架构中的表是的,在我授予您对它们的权限之前,您甚至看不到它们。

语法很简单:所有者模式问题

grant select, insert on my_table to you
/

或者,具有 GRANT ANY 权限的帐户(例如 DBA)可以传递对任何用户对象的权限。

grant select, insert on apc.my_table to you
/

被授权者可以是用户或角色。但是,请注意,我们只能使用直接授予我们用户的权限来构建程序单元 - 存储过程、视图、触发器。

因此,如果您让其他架构所有者授予您必要的权限,您将能够构建您的触发器。

编辑

当引用另一个模式中的对象时,我们需要使用模式名称来限定对象......

insert into apc.whatever_table  values ...

否则我们需要为它创建一个同义词

create synonym whatever for apc.whatever_table;
于 2010-04-16T23:06:37.460 回答
2

我觉得有人应该添加显而易见的 - 另一个模式的表必须用模式名称限定,或者需要私有/公共同义词。我想知道最初的问题是否仅仅是名称解析问题。如果不是,APC 的回答是对 Oracle 安全模型的一个很好的解释。

于 2010-04-17T00:22:34.073 回答
0

您应该为涉及的每个表和架构执行此操作:

grant select on OTHER_SCHEMA_%.table_name to MAIN_SCHEMA;
于 2010-04-20T12:55:45.490 回答