Oracle dropping and recreating synonyms - oracle

When we use CTAS like this:
create table big2 as select * from big1;
drop table big1;
rename big2 to big1;
If there are synonym existing on big1, do we need to drop synonym on big1 prior to delete and recreate them? Or is this not necessary?

No. Becuase Synonym is just another name you give to an object ( either within your schema or not). See this code below.
(BTW, shouldn't you rename table t2 to t1 directly?? Does your CTAS have other where conditions, which you are not showing here?)
SQL> create table t1 as
2 select * from scott.emp;
Table created.
SQL> select count(*) from t1;
COUNT(*)
----------
14
SQL> select count(*) from t2;
select count(*) from t2
*
ERROR at line 1:
ORA-00942: table or view does not exist
SQL> create synonym s1 for t1;
Synonym created.
SQL> create table t2 as
2 select * from t1;
Table created.
SQL> drop table t1;
Table dropped.
SQL> alter table t2 rename to t1;
Table altered.
SQL> select count(*) from t1;
COUNT(*)
----------
14
SQL> select count(*) from s1;
COUNT(*)
----------
14

Related

How to find sequnce name which associated to table with table name

How to find sequnce name which is associated to mytable in Oracle sql
Select * user_sequwnces where table_name =tablename
If you created a table using the IDENTITY clause, then the sequence name will aligned with the object ID of the table, eg
SQL> create table t ( x int generated as identity);
Table created.
SQL> select object_id from user_objects
2 where object_name = 'T';
OBJECT_ID
----------
4282429
SQL> select sequence_name
2 from user_sequences
3 where sequence_name like '%4282429%';
SEQUENCE_NAME
-----------------------------------------------------
ISEQ$$_4282429
But if you just use a sequence of your own as a default, there is no such relationship, eg
SQL> create sequence blah;
Sequence created.
SQL> create table t1 ( x int default blah.nextval, y int );
Table created.
SQL> create table t2 ( x int default blah.nextval, y int );
Table created.
SQL> create table t3 ( x int default blah.nextval, y int );
Table created.
You can even drop the sequence ... and that only would become an issue later when you try to use it, eg
SQL> drop sequence blah;
Sequence dropped.
SQL> insert into t1 (x,y) values (0,0);
1 row created.
SQL> insert into t1 (y) values (0);
insert into t1 (y) values (0)
*
ERROR at line 1:
ORA-02289: sequence does not exist

Oracle DB: Scheduled job failing with error: ORA-06576: not a valid function or procedure name

I am trying to create a scheduled job in Oracle DB, from which, I need to execute a stored procedure.
I have created the procedure like:
CREATE OR REPLACE PROCEDURE "delete_old_transactions" AS
BEGIN
DELETE from EVENT_JOURNAL where EVENT_JOURNAL.WRITE_TIMESTAMP < (((SYSDATE-CAST(TO_TIMESTAMP_TZ('01-01-1970 00:00:00+00:00', 'DD-MM-YYYY HH24:MI:SS TZH:TZM') as date)) * 24 * 60 * 60 * 1000) - (4 * 24 * 60 * 60 * 1000));
DELETE from SNAPSHOT where SNAPSHOT.CREATED < (((SYSDATE-CAST(TO_TIMESTAMP_TZ('01-01-1970 00:00:00+00:00', 'DD-MM-YYYY HH24:MI:SS TZH:TZM') as date)) * 24 * 60 * 60 * 1000) - (4 * 24 * 60 * 60 * 1000));
END;
The stored procedure compiles fine and gets created successfully.
I created the scheduled job like:
BEGIN
DBMS_SCHEDULER.CREATE_JOB (
job_name => 'delete_old_transactions_job',
job_type => 'STORED_PROCEDURE',
start_date => SYSTIMESTAMP,
enabled => true,
job_action => 'delete_old_transactions',
repeat_interval => 'FREQ=MINUTELY;INTERVAL=2;',
job_class => 'DEFAULT_JOB_CLASS',
comments => 'Job for deleting old transactions.');
END;
The scheduled job also gets created and is executing after every 2 minutes as desired, but it is failing in the execution and returns an error:
ORA-06576: not a valid function or procedure name.
This is wrong:
CREATE OR REPLACE PROCEDURE "delete_old_transactions"
- -
this this
Why did you use double quotes? Remove them. In Oracle, everything is stored into data dictionary in uppercase, but you can reference them any way you want (upper/lower/mixed case).
But, if you use double quotes while creating objects, you have to use the same double quotes and match letter case exactly every time you reference those objects.
Therefore, the simplest option is to recreate the procedure, but this time remove double quotes.
Or, put double quotes into DBMS_SCHEDULER:
job_action => '"delete_old_transactions"',
but that's not particularly good idea.
Perhaps this will help in understanding how oracle treats case-sensitivity of object names. Here I am playing with table names, just for the sake of a simpler demo. But the same applies to all object names - tablespaces, tables, columns, functions, procedures, packages, etc.
Pay close attention to the treatment of the table name:
SQL> conn scott/tiger#pdb01
Connected.
SQL> --
SQL> select banner from v$version;
BANNER
--------------------------------------------------------------------------------
Oracle Database 19c Enterprise Edition Release 19.0.0.0.0 - Production
1 row selected.
SQL> --
SQL> -- Create mixed-case table
SQL> create table "MyDemo"
2 (col1 varchar2(20))
3 ;
Table created.
SQL> insert into "MyDemo" values ('mixed case');
1 row created.
SQL> -- create default case table
SQL> create table MyDemo
2 (col1 varchar2(20));
Table created.
SQL> insert into MyDemo values ('default');
1 row created.
SQL> --
SQL> select table_name
2 from user_tables
3 where upper(table_name)='MYDEMO';
TABLE_NAME
--------------------
MyDemo
MYDEMO
2 rows selected.
SQL>
SQL> select * from mydemo;
COL1
--------------------
default
1 row selected.
SQL> select * from MyDemo;
COL1
--------------------
default
1 row selected.
SQL> select * from "MyDemo";
COL1
--------------------
mixed case
1 row selected.
SQL> -- clean up
SQL> drop table mydemo;
Table dropped.
SQL> drop table "MyDemo";
Table dropped.
SQL> --
SQL> spo off
SQL> edit demo.log
SQL> insert into MyDemo values ('default');
1 row created.
SQL> --
SQL> select table_name
2 from user_tables
3 where upper(table_name)='MYDEMO';
TABLE_NAME
--------------------
MyDemo
MYDEMO
2 rows selected.
SQL>
SQL> select * from mydemo;
COL1
--------------------
default
1 row selected.
SQL> select * from MyDemo;
COL1
--------------------
default
1 row selected.
SQL> select * from "MyDemo";
COL1
--------------------
mixed case
1 row selected.
SQL> -- clean up
SQL> drop table mydemo;
Table dropped.
SQL> drop table "MyDemo";
Table dropped.

Create Table from Query IN PLSQL

Since complex query takes long time to execute so I want to create a table to keep for future use, I don't want to execute it again. so my idea is that I want to create a table by insert query result into it.
The below is my sample code. It is not working it is just my idea. Thanks
DECLARE
with tab_emp as (
select * from employees
),
tab_dept as
(select * from departments)
procedure create_tab_from_query IS
begin
EXECUTE IMMEDIATE ('create table mytest as select * from '|| tab_emp || ' where 1=0');
end create_tab_from_query;
BEGIN
create_tab_from_query;
dbms_output.put_line(abc);
END;
/
This works:
SQL> with t2 as (select * from t) select * from t2;
L A
--------- ------------------------------------------------------
RUS Русский
But you cannot use WITH in a CREATE TABLE statement as you would like to use.
This cannot work:
SQL> with t2 as (select * from t) create table t3 as select * from t2;
with t2 as (select * from t) create table t3 as select * from t2
*
ERROR at line 1:
ORA-00928: missing SELECT keyword
You should try something simpler without WITH clause:
SQL> create table t3 as select * from t;
Table created.
In your case your PL/SQL code could be simplified this way:
SQL> --
SQL> BEGIN
2 EXECUTE IMMEDIATE ('
3 create table mytest as select * from employees where 1=0');
4 dbms_output.put_line('abc');
5 END;
6 /
abc
PL/SQL procedure successfully completed.

Count of table before and after insert inside a trigger

Is it possible to check the count of a table before any changes happen and the count after the insert and match them inside the same trigger?
for ex: old.count and new.count (before and after insert) ?
old.count and new.count (before and after insert)
Nothing stops you from using SELECT COUNT(*) in a before insert trigger. Of course, you won't do it in a after insert trigger, since a select count(*) on the same table on which an after trigger is defined would throw mutating table error. One way is autonomous transaction. But, in your case, it isn't that complex.
You could define a BEFORE INSERT TRIGGER and take the table count. The after insert count could be taken manually after the actual insert is done.
For example, I have a table t1 with one row. I have defined a before insert trigger on it, which would give me the table count before the insert happens.
SQL> DROP TABLE t1 PURGE;
Table dropped.
SQL>
SQL> CREATE TABLE t1 (A NUMBER);
Table created.
SQL>
SQL> INSERT INTO t1 VALUES (1);
1 row created.
SQL>
SQL> SELECT * FROM t1;
A
----------
1
SQL>
SQL> CREATE OR REPLACE TRIGGER trg
2 BEFORE INSERT
3 ON t1
4 FOR EACH ROW
5
6 DECLARE
7 val number;
8 BEGIN
9 SELECT COUNT(*)
10 INTO val
11 FROM t1;
12
13 DBMS_OUTPUT.PUT_LINE('TABLE COUNT BEFORE INSERT = '||val);
14
15 END;
16 /
Trigger created.
SQL>
SQL> set serveroutput on
SQL> INSERT INTO t1 VALUES (1);
TABLE COUNT BEFORE INSERT = 1
1 row created.
SQL>
SQL> SELECT COUNT(*) FROM t1;
COUNT(*)
----------
2
SQL>
So, you see TABLE COUNT BEFORE INSERT = 1 and then after insert the count is 2.

Does altering or drop-recreating a table in oracle affects the policies defined on it

If i have a table and a defined policy on it then do I need to redefine the policy if I drop and recreate the table or alter it, provided that the alteration or the recreation of the table does not alter elements that the function needs to see?
"do I need to redefine the policy if I
drop and recreate the table"
Yes. Let's create a policy.
SQL> exec dbms_rls.add_policy('APC', 'T23', 'DEPTPOL', 'APC', 'security_policies.get_deptno_predicate')
PL/SQL procedure successfully completed.
SQL> select count(*) from user_policies;
COUNT(*)
----------
1
SQL> exec security_policies.set_deptno(20)
PL/SQL procedure successfully completed.
SQL> select count(*) from t23;
COUNT(*)
----------
6
SQL>
so that works. But if we drop and re-create the table (using a backup I prepared earlier) ...
SQL> drop table t23
2 /
Table dropped.
SQL> create table t23 as select * from t23a
2 /
Table created.
SQL> select count(*) from t23;
COUNT(*)
----------
11
SQL> exec security_policies.set_deptno(20)
PL/SQL procedure successfully completed.
SQL> select count(*) from t23;
COUNT(*)
----------
11
SQL> SQL> select count(*) from user_policies;
COUNT(*)
----------
0
SQL>
"So the question is if I must redefine
the policy even if I will not change
anything in the definition."
No. Providing the change doesn't invalidate the generated predicate altering a table doesn't drop the policy:
SQL> exec dbms_rls.add_policy('APC', 'T23', 'DEPTPOL', 'APC', 'security_policies.get_deptno_predicate')
PL/SQL procedure successfully completed.
SQL> alter table t23 modify deptno number(3,0)
2
SQL> desc t23
Name Null? Type
----------------------------------------- -------- ----------------------------
NAME VARCHAR2(12 CHAR)
ID NUMBER
AGE NUMBER(4)
DEPTNO NUMBER(2)
SQL> alter table t23 modify deptno number(3,0)
2 /
Table altered.
SQL> exec security_policies.set_deptno(20)
PL/SQL procedure successfully completed.
SQL> select count(*) from t23;
COUNT(*)
----------
6
SQL>
Note that the change modified the column which is tested by the predicate and the policy still remains in force.
"does a 'CREATE OR REPLACE VIEW'
statement drops and recreates it or
does it alter it?"
Let's try it:
SQL> create view v23 as select * from t23;
View created.
SQL> exec dbms_rls.add_policy('APC', 'V23', 'DEPTPOLV', 'APC', 'security_policies.get_deptno_predicate')
PL/SQL procedure successfully completed.
SQL> exec security_policies.set_deptno(10)
PL/SQL procedure successfully completed.
SQL> select count(*) from v23;
COUNT(*)
----------
5
SQL> create or replace view v23 as select name, age from t23;
View created.
SQL> select count(*) from v23;
select count(*) from v23
*
ERROR at line 1:
ORA-28113: policy predicate has error
SQL>
Okay, so that's an error because the view's new projection doesn't include the column in the predicate. But it suggests teh ploicy is still in place. So let's fix that error:
SQL> create or replace view v23 as select name, age, deptno from t23;
View created.
SQL> select count(*) from v23;
COUNT(*)
----------
5
SQL>

Resources