views:

394

answers:

3

I'm trying to write a table trigger which queries another table that is outside the schema where the trigger will reside. Is this possible? It seems like I have no problem querying tables in my schema but I get:

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

when trying trying to query tables outside my schema.

EDIT

My apologies for not providing as much information as possible the first time around. I was under the impression this question was more simple.

I'm trying create a trigger on a table that changes some fields on a newly inserted row based on the existence of some data that may or may not be in a table that is in another schema.

The user account that I'm using to create the trigger does have the permissions to run the queries independently. In fact, I've had my trigger print the query I'm trying to run and was able to run it on it's own successfully.

I should also note that I'm building the query dynamically by using the EXECUTE IMMEDIATE statement. Here's an example:

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;

The trigger seams to fail on the EXECUTE IMMEDIATE with the previously mentioned error.

EDIT

I have done some more research and I can offer more clarification.

The user account I'm using to create this trigger is not MAIN_SCHEMA or any one of the OTHER_SCHEMA_Xs. The account I'm using (ME) is given privileges to the involved tables via the schema users themselves. For example (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

And I have the following system privileges (USER_SYS_PRIVS):

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

And this is what I found in the Oracle documentation:

To create a trigger in another user's schema, or to reference a table in another schema from a trigger in your schema, you must have the CREATE ANY TRIGGER system privilege. With this privilege, the trigger can be created in any schema and can be associated with any user's table. In addition, the user creating the trigger must also have EXECUTE privilege on the referenced procedures, functions, or packages.

Here: Oracle Doc

So it looks to me like this should work, but I'm not sure about the "EXECUTE privilege" it's referring to in the doc.

+5  A: 

What you are experiencing is a feature of Oracle's security model. The entire point of using schemas is to control access to the data. The tables in my schema are mine, you cannot even see them until I grant you privileges on them.

The syntax is quite simple: the owner schema issues

grant select, insert on my_table to you
/

Alternatively an account with the GRANT ANY privilege (such as a DBA) can pass privileges on any user's objects.

grant select, insert on apc.my_table to you
/

The grantee can be either a user or a role. However, note that we can only build program units - stored procedures, views, triggers - using privileges which have been granted directly through to our user.

So, if you get the other schema owner to grant you the necessary privileges you will be able to build your trigger.

edit

When referencing an object in another schema we need to qualify the object with the schema name ....

insert into apc.whatever_table  values ...

or else we need to create a synonym for it

create synonym whatever for apc.whatever_table;
APC
this was my thought also, was waiting on clarifcation
ninesided
+2  A: 

I feel someone should add the obvious - the other schema's table must be qualified with the schema name or a private/public synonym is needed. I wonder if the original problem was merely a name resolution issue. If not, APC's answer is a good explanation of the Oracle security model.

dpbradley
i agree here: select * from anothershema.table
Randy
A: 

You should execute this for every table and schema involved:

grant select on OTHER_SCHEMA_%.table_name to MAIN_SCHEMA;
Florin Ghita
APC was on the right track and you hit it home, probably because I finally got all the pertinent information together. Unfortunately, I can't verify, because I don't have the necessary levels of access and I already told the DBAs I would handle the problem in my application logic. You'd think that they would have know this from the beginning... Anyway, thanks everyone!
sisslack