ORA-04089: cannot create triggers on objects owned by SYS - database

I want to create trigger but i get this error.ORA-04089: cannot create triggers on objects owned by SYS
04089. 00000 - "cannot create triggers on objects owned by SYS"
How can i solve this problem?.Why cannot I create triggers on objects owned by SYS?
create table superhero(name varchar2(30));
create or replace trigger tg_sup
before insert on superhero
for each row disable
declare
v_user varchar2(30);
begin
select user into v_user from dual;
DBMS_OUTPUT.PUT_line('you just inserted a line by '||v_user);
end;

As you were told: you can't do it in SYS schema. It, just like SYSTEM, is special, it owns the database and should only be used for maintenance purposes. Create your own user to brush SQL skills; for example, I have the scott user:
SQL> create table superhero
2 (name varchar2(30));
Table created.
SQL> create or replace trigger tg_sup
2 before insert on superhero
3 for each row
4 disable
5 declare
6 v_user varchar2(30);
7 begin
8 select user into v_user from dual;
9 DBMS_OUTPUT.PUT_line('you just inserted a line by '||v_user);
10 end;
11 /
Trigger created.
Let's try it:
SQL> set serveroutput on
SQL> insert into superhero(name) values ('Littlefoot');
1 row created.
Good; but, there's no message (from the trigger). How come? Because you chose to create it in disabled state (why did you do that?):
SQL> select status from user_Triggers where trigger_name = 'TG_SUP';
STATUS
--------
DISABLED
If we enable it:
SQL> alter trigger tg_sup enable;
Trigger altered.
SQL> insert into superhero(name) values ('Bigfoot');
you just inserted a line by SCOTT --> message!
1 row created.
SQL>
OK, message is being displayed.

Related

Oracle change column datatype from varray

In Oracle database I have two schemas with two tables that mirror each other, except for one column which in both tables is varray of numbers, but in schema A it's A.VARRAY, and in schema B it's B.VARRAY.
As a result I'm unable to migrate data between tables, since they have inconsistent datatypes.
Is there any way to change column datatype from A.varray to B.varray without losing data?
Just use cast(col as B.VARRAYTYPE):
SQL> CREATE OR REPLACE TYPE V_TYPE_1 AS VARRAY(5000) OF NUMBER(1);
2 /
Type created.
SQL> CREATE OR REPLACE TYPE V_TYPE_2 AS VARRAY(5000) OF NUMBER(1);
2 /
Type created.
SQL> create table t1 (a V_TYPE_1);
Table created.
SQL> insert into t1 values(v_type_1(1,2,3,4,5));
1 row created.
SQL> create table t2 (a V_TYPE_2);
Table created.
SQL> insert into t2 select cast(a as v_type_2) from t1;
1 row created.
SQL> select * from t2;
A
-------------------------
V_TYPE_2(1, 2, 3, 4, 5)
1 row selected.
CAST it is, I agree with Sayan. Though, as there are two users involved, there are some in-between steps required - grant execute on type being most important, I'd say. Here's an example.
My users are scott and mike. Each of them has the same table description. scott is supposed to insert rows into mike's table.
Connected as scott:
SQL> show user
USER is "SCOTT"
SQL> create or replace type v_type as varray(5000) of number(1);
2 /
Type created.
SQL> create table test (id number, a v_type);
Table created.
SQL> insert into test(id, a) values (1, v_type(1));
1 row created.
SQL>
Connected as mike: uses the same type as scott:
SQL> show user
USER is "MIKE"
SQL> create or replace type v_type as varray(5000) of number(1);
2 /
Type created.
SQL> create table test (id number, a v_type);
Table created.
SQL> grant insert on test to scott;
Grant succeeded.
SQL>
Connected as scott, trying to insert row(s) into mike's table:
SQL> show user
USER is "SCOTT"
SQL> insert into mike.test (id, a) select id, a from test;
insert into mike.test (id, a) select id, a from test
*
ERROR at line 1:
ORA-00932: inconsistent datatypes: expected MIKE.V_TYPE got SCOTT.V_TYPE
Let's try CAST:
SQL> insert into mike.test (id, a) select id, cast(a as mike.v_type) from test;
insert into mike.test (id, a) select id, cast(a as mike.v_type) from test
*
ERROR at line 1:
ORA-00904: : invalid identifier
SQL>
In order to make it work, mike has to grant execute on their type to scott:
SQL> show user
USER is "MIKE"
SQL> grant execute on v_type to scott;
Grant succeeded.
SQL>
Finally, it works:
SQL> show user
USER is "SCOTT"
SQL> insert into mike.test (id, a) select id, cast(a as mike.v_type) from test;
1 row created.
SQL>
Would you be willing to add a column to one of the tables, populate the new column with values from the other column, say through an update statement, then drop old column?
T1(c1 V_TYPE_1);
T2(c1 V_TYPE_2);
(1) Add column to T2:
T2(c1 V_TYPE_2, c2 V_TYPE_1);
(2) Update T2 so c1 and c2 are the same values for every row.
(3) Drop old column from T2:
T2(c2 V_TYPE_1);
This solution would be a little easier if the table was not active. If the table was active you will want to add a trigger so that the two columns are in sync.

Will deleting column data reduce database size?

I have a table with several columns, one of which is a CLOB containing large XML project file data. That one column accounts for 99% of the size of that table, and the table has grown to several Gb. Our DBA needs to migrate the database and wants to reduce the size as much as possible beforehand. We can't lose any rows from that table but we would be safe in clearing out the data in that particular CLOB column. Would updating the table to remove that data reduce the overall size (I assume if it did it would be in conjunction with some administrative re-indexing action or something)?
If you don't need any CLOB data, drop that column:
SQL> create table test
2 (id number,
3 cclob clob);
Table created.
SQL> insert into test (id, cclob) values (1, 'Littlefoot');
1 row created.
SQL> alter table test drop column cclob;
Table altered.
SQL>
Alternatively, create a new table with primary key column and CLOB column:
SQL> desc test
Name Null? Type
----------------------------------------- -------- ------------------
DEPTNO NUMBER(2)
DNAME VARCHAR2(14)
LOC VARCHAR2(13)
CCLOB CLOB
SQL> create table new_test as select deptno, cclob from test;
Table created.
SQL> alter table test drop column cclob;
Table altered.
SQL>
Now you can move the new, lightweight table to another server. If you need some of CLOB data, you can update the new table (on a new server) as
SQL> update test_on_new_server a set
2 a.cclob = (select b.cclob
3 from test_from_old_server b
4 where b.deptno = a.deptno
5 )
6 where a.loc = 'NEW YORK';

Create a copy of a table with data without logging

Is there an easy way to copy the data of a table to the same database with different table name without logging.
CREATE TABLE SCHEMA.NEW_TB LIKE SCHEMA.OLD_TB;
INSERT INTO SCHEMA.NEW_TB (SELECT * FROM SCHEMA.OLD_TB);
The above 2 statements will work but the table contains huge amount of data. So is it possible to copy the data without logging?
Use the following with auto commit switched off in your session:
CREATE TABLE SCHEMA.NEW_TB LIKE SCHEMA.OLD_TB;
COMMIT;
ALTER TABLE SCHEMA.NEW_TB ACTIVATE NOT LOGGED INITIALLY;
INSERT INTO SCHEMA.NEW_TB
SELECT * FROM SCHEMA.OLD_TB;
COMMIT;
It’s important to use ALTER TABLE and INSERT in the same transaction.

SQL Server 2008 view is losing the default value

I have a strange issue, after some time after a view is created, the default value for applicationID is lost or reset (we don't know why, we had something like 0.000 or 0 or null).
CREATE VIEW [schemaA].[tableA]
AS
SELECT
*, 123456 applicationID
FROM
[schemaB].[dbo].[tableA]
If we run an ALTER statement, the value of applicationID returns back to the originally defined value.
ALTER VIEW [schemaA].[tableA]
AS
SELECT
*, 123456 applicationID
FROM
[schemaB].[dbo].[tableA]
I need to mention that before running the ALTER statement, we exported the view DDL and it was correct.
How can I identify what is corrupting the view definition or if the view should have a different definition (maybe set a default value if it's possible).
Thank you
Could it be something like this?
CREATE TABLE testTbl(aColumn INT);
INSERT INTO testTbl VALUES(1),(2);
GO
CREATE VIEW vwTestTbl
AS
SELECT *,1234 applicationID
FROM testTbl;
GO
SELECT * FROM vwTestTbl;
/*
aColumn applicationID
1 1234
2 1234
*/
GO
--be aware of the fact, that the new column is called newColumn and its type is varchar(5)!
ALTER TABLE testTbl ADD newColumn varchar(5);
GO
UPDATE testTbl SET newColumn='test';
GO
--The varchar value "test" comes under the column caption "applicationID"!
SELECT * FROM vwTestTbl;
/*
aColumn applicationID
1 test
2 test
*/
GO
--now you re-compile it with your attempt to ALTER the VIEW
ALTER VIEW vwTestTbl
AS
SELECT *,1234 applicationID
FROM testTbl;
GO
SELECT * FROM vwTestTbl;
/*
aColumn newColumn applicationID
1 test 1234
2 test 1234
*/
GO
--clean up
DROP VIEW vwTestTbl;
DROP TABLE testTbl;

Does dropping a database user drop triggers the user has raised on tables from other schemas?

Assuming a user USER1 has created triggers on various tables, all of which are not owned by this user but these triggers record data to USER1 tables.
Now, if I drop a user in Oracle using the following command, will this drop all these other triggers as well?
SQL>drop user USER cascade;
If not, the triggers will not work as they will not find the destination tables to write to. Also, is there a way to drop all triggers raised by a database user irrespective of the schema to which they belong?
A simple test shows that the triggers will be dropped. I created a new user TEST2, granted it CREATE ANY TRIGGER, then created a single trigger on PHIL.BIGTABLE.
PHIL#PHILL11G2 > select count(*) from dba_triggers;
COUNT(*)
----------
617
PHIL#PHILL11G2 > drop user test2 cascade;
User dropped.
PHIL#PHILL11G2 > select count(*) from dba_triggers;
COUNT(*)
----------
616
PHIL#PHILL11G2 >
Trigger metadata is in DBA_TRIGGERS, so dropping them is a matter of:
begin
for x in (
select owner,
trigger_name
from dba_triggers
where ... -- apply predicate to select triggers here)
loop
execute immediate 'drop trigger '||x.owner||'.'||x.trigger_name;
end loop;
end;
/

Resources