I want to auto increment a column and make it as a primary key in oracle10g. But on trigger creation I get an error - oracle

I have created a Sequence for the table and on creation of a trigger I got the following error:
ORA-04089: cannot create triggers on objects owned by SYS.
Can someone explain me what is it and how can it be solved? Since I'm a beginner, is there a simple way to solve it?
MY TABLE NAME IS-testing.
create sequence example_seq
start with 1
increment by 1
nomaxvalue;
create trigger example_trigger
before insert on testing
for each row
begin
select example_seq.nextval into :new.id from dual;
end;

The error message is quite clear:
ORA-04089: cannot create triggers on objects owned by SYS.
So obviously you are logged in as SYS, and creating objects in that user;s schemas. You must not do this. SYS is the user who owns the data dictionary and all the objects which manage the database. Changing the SYS schema is, at best, bad practice and runs the risk of corrupting the database. Find out more.
What you need to do is create a new user, for your application objects. This is quite simple. Connect as SYSTEM (avoid using SYS for menial tasks):
create user your_name_here identified by << password >>
/
grant create session, create table, create sequence, create trigger
to your_name_here
/
Obviously you will need to grant more privileges. The full list is in the documentation.
Once you've created your new user you can connect to it and create all the objects you desire.

Related

grant select any table from one specific schema

I have just created a new read only user (TEMPDBREAD) for our developers # our oracle Database 11.2.0.4
Now they like read access to all tables from just one schema (TEMPDBUSER)
is there an alternative to grant select any table.
They should not be able to read the other schemes. But since the table structure often changes, it is difficult to justify everything manually.
That's why select any table is awarded very quickly and easier to place
Can i deny the access to the other schemes anyway?
Any Idea how i can solve this very simple?
BR Julian
Grant Table Access manually
Grant Select ANY Table
Nope. You either give them select any table and let them read any table in the database or you give them access to each table in TempDBUser individually. In the vast, vast majority of cases, you'd want to give them access to each table in TempDBUser (presumably via a role because there will be many developer accounts that need to run queries).
It isn't clear to me why giving object-level access is problematic for you. "Table structure changes" do not require new grants since they're just changes to existing objects. If you really mean that new tables are created frequently, you'd just want to incorporate the grants into your change control and deployment process.
If you have a packaged application that creates new tables periodically (a terrible practice), you could create a DDL trigger that issued the grant every time a new table was created in TempDBUser. You'd need a DDL trigger that submitted a job via the dbms_job package that did the actual grant which is a rather convoluted architecture but it works.
spool /tmp/grant_issue.sql
select 'grant select on TEMPDBUSER.' || table_name || ' TO TEMPDBREAD;' from dba_tables where owner='TEMPDBUSER' ;
spool off;
run the spool file.
sqlplus #/tmp/grant_issue.sql

How to GRANT SELECT to ANY Table in a Schema to a Role (Oracle)

We wish to create an ANALYTICS role on our Oracle database. Anyone in this ANALYTICS role should be able to SELECT across any views in one (or more) schemas, but not ALL schemas.
We have a schema called ARIEL for example, and when we create new tables and views, we don't want to have to constantly apply GRANTS to the ANALYTICS role, and so we are hoping there is a way to apply a grant like this "GRANT SELECT ON ALL TABLES IN SCHEMA_X TO ANALYTICS"...note ANALYTICS is a role, not a schema.
Our DBA is saying this is not possible, and any future objects we create will need to have a grant applied, giving access to the ROLE.
"Our DBA is saying this is not possible, and any future objects we create will need to have a grant applied, giving access to the ROLE."
Your DBA is correct. You are searching for schema wide privileges(not implemented yet).
More: GRANT SELECT on all tables in a schema
Your DBA is correct that there would need to be a grant for every object that is created. It is possible to automate this which gives you basically the behavior that you want. I've done this in the past. But I'd seriously question the requirement before implementing it.
In general, new tables aren't created in production automatically, they're created as part of a build process. Part of that build process involves doing things like figuring out who should have access to the tables. Assuming that you're going through some sort of source control system, that means that you've got a history of the grants on objects and you can tie back changes in those grants to user stories. That's a useful thing to have.
If you have applications that are creating new tables in production dynamically (like an off the shelf app I was supporting) or doing something else where giving grants as part of a build process would be problematic, you can automate the process with a DDL trigger.
Create a DDL trigger that fires when a table is created
In that DDL trigger, use dbms_job to run a grant statement immediately after the CREATE TABLE statement commits
Something like this should work (untested)
CREATE OR REPLACE TRIGGER ddl_create
AFTER CREATE ON SCHEMA
DECLARE
l_job BINARY_INTEGER;
l_sql VARCHAR2(4000);
BEGIN
IF ora_dict_obj_type = 'TABLE'
THEN
l_sql := 'grant select on ' ||
ora_dict_obj_owner || '.' || ora_dict_obj_name ||
' to analytics';
DBMS_JOB.SUBMIT (
job => l_job,
what => l_sql );
END IF;
END;
Since the job runs asynchronously, it is possible that it will take a second or two to run after the table is created which may be an issue if the application immediately tries to run a query on the object. It is also possible that your DBA may disable jobs or limit the number of jobs that can run simultaneously which could further delay the grant. And if something goes wrong with the trigger or the job, this is a sufficiently obscure approach that it is going to take people a while to figure out where the problem is. DBAs aren't in the habit of looking for DDL triggers that may be granting privileges when someone decides, say, that they want a new role to automatically get insert access on the new table or when a grant didn't happen because jobs were disabled.

Add username into another table while creating a new Oracle user

I am creating a simple application where I am using a Servlet and JDBC to create users.
Is there any way I can use a trigger to insert the username into another table when the Oracle user is created with:
create user xyz ......
Once this query executes successfully, it inserts the user information in the DBA_USERS table.
I want the username to also be inserted into another table. Should I add it to that other table manually through JDBC, or can I create a trigger to do it automatically?
You could use a system trigger based on the create user DDL (but not a DML trigger on the dba_users view - you can't do that anyway, but don't even think about trying to do anything based on the data dictionary). But you wouldn't really have any way for that to know if the user being created is actually an application user - you'd be assuming any user added to the DB could only be related to your application.
Since you have to take other steps anyway - such as granting roles and/or privileges, maybe adding other application security data, etc., it probably makes more sense to do the table insert manually.
It may even make more sense to put all the user-creation code into a stored (and probably packaged) procedure, and just call that over JDBC; the downside of that is that the create user and any other DDL would need to be executed from within the procedure as dynamic SQL. Any of your own table inserts would be together though, and you'd only have that single JDBC call to make.
You can also have other procedures to modify and delete users.
Something to bear in mind, however you do it, is that DDL implicitly commits. Not necessarily a problem, just something to be aware of, so you can order the steps in a recoverable way.

Why cannot I create triggers on objects owned by SYS?

While trying to create a trigger named ghazal_current_bef_upd_row :
create trigger ghazal_current_bef_upd_row
before update on ghazal_current
for each row
when (new.Rating < old.Rating)
begin
insert into ghazal_current_audit
(GhazalName,Old_Rating,New_Rating)
values
(:old.GhazalName,:old.Rating,:new.Rating);
end;
I get the following error :
Error report:
ORA-04089: cannot create triggers on objects owned by SYS
04089. 00000 - "cannot create triggers on objects owned by SYS"
*Cause: An attempt was made to create a trigger on an object owned by SYS.
*Action: Do not create triggers on objects owned by SYS.
Both the tables named ghazals_current and ghazal_current_audit were created by SYS. Why cannot I create a trigger on the table created by SYS .
You should not be creating any objects in the SYS schema. That user is part of the Oracle database management system, and changing its schema is likely to break your database. Certainly it could invalidate your Oracle Support contract (if you have one). From the documentation:
"The administrative account SYS is automatically created when a
database is created. This account can perform all database
administrative functions. The SYS schema stores the base tables and
views for the data dictionary. These base tables and views are
critical for the operation of Oracle Database. Tables in the SYS
schema are manipulated only by the database and must never be modified
by any user."
Oh, in case you're wondering, the same applies to SYSTEM too.
Triggers are particularly prone to abuse and are a major source of scaling problems. That's why Oracle forbids us to build triggers in SYS, because doing so might corrupt or at least impact the performance of the data dictionary.
Of course that's not what's happening here. You have built your own tables in SYS. Well drop them. Now. Use SYS to create your own user, GHAZAL or whatever name suits, and grant it the required privileges: CREATE SESSION, CREATE TABLE, CREATE TRIGGER, and so forth. Then connect as that new user to create your tables and other schema objects.

Preventing a user from dropping its' own trigger

I have created a read only user A in Oracle DB. (who can access schema X but cannot alter anything) Then i am asked to give user A create table privilege on schema X.
However as far as i know, i can either give create any table privilege to user A or create table privilege. One of them is for creating table on his/her own schema, other one is for creating table on all schemas, which should not be preferred.
So i have given create any table privilege to user A and then created a trigger which prevents user A from creating a table on schemas other than X.
HOWEVER,
I needed to create the trigger as user A, and now user A can easily drop that trigger because A is the owner.
Is there any way i can prevent user A from dropping triggers even if he/she's the owner ?
As far as i experienced,user A does not need to have drop any trigger or administer database trigger privileges since trigger is already his/her own.
Is there any workaround for this ? Or should i search for an alternative way to give create table permission on other schemas.
Thank you in advance.
No, there is no way to prevent a user from dropping an object that it owns.
There's also no way to directly allow for user A to create objects in user X's schema, unless you start granting "ANY" privileges.
One possible workaround may be to create a stored procedure in user X's schema that will create objects in user X's schema (execute immediate) and grant EXECUTE privilege on said stored procedure to user A.
So, in this way, user A could do something like:
exec create_in_x_schema('create table blah(a number)');
And that procedure would just do an execute immediate on the string passed in.
A procedure that looks something like:
create or replace procedure create_in_x_schema(doit varchar2)
begin
execute immediate doit;
end;
/
ought to do it.
(Code is untested, but should give you some idea.)
Hope that helps.

Resources