问题
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.
回答1:
You should execute this for every table and schema involved:
grant select on OTHER_SCHEMA_%.table_name to MAIN_SCHEMA;
回答2:
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;
回答3:
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.
来源:https://stackoverflow.com/questions/2656481/multi-schema-privileges-for-a-table-trigger-in-an-oracle-database