altering Table Owner of multiple synonyms - oracle

I have 848 NONEDITIONABLE PUBLIC SYNONYM that have the TABLE_OWNER as Dev.
I want help to alter all these NONEDITIONABLE PUBLIC SYNONYM to Prod, but in order to do so we need to extract all the queries. Is there a query to do so?
current:
CREATE OR REPLACE NONEDITIONABLE PUBLIC SYNONYM "CONFIG_SEQ" FOR "Dev"."CONFIG_SEQ";
expected:
CREATE OR REPLACE NONEDITIONABLE PUBLIC SYNONYM "CONFIG_SEQ" FOR "Prod"."CONFIG_SEQ";
your time and help is appreciated.
Thank You

we need to extract all the queries. Is there a query to do so?
Yes. Generate the script from the data dictionary:
select 'CREATE OR REPLACE NONEDITIONABLE PUBLIC SYNONYM "'
|| synonym_name ||'" FOR "PROD"."' || table_name || '";'
from all_synonyms
where owner = 'PUBLIC'
and table_owner = 'DEV'
/
For future reference please remember that needing to do this is a failure of process. DDL scripts are just like any other code, and should be kept in a source control repository, and checked out and deployed through managed releases.

Related

how to track and modify an in-flight oracle query before execution?

My Application is sending below query to Oracle.
SELECT * FROM EMPLOYEE WHERE DATE > (SYSDATE - 1) order by employee_id
I cannot change this query from the application. I am looking for a way for oracle to monitor the queries, change it to below query format and return the result.
SELECT * FROM EMPLOYEE WHERE DATE > (SYSDATE - 1) and Currently_employed = 'YES' order by employee_id
Thank You.
Subrat
If the application can connect to the database as a different user then the table owner, you could also implement a Virtual Private Database policy to modify the query in-flight. See here:
https://oracle-base.com/articles/8i/virtual-private-databases
You could also, if the application is connecting as a separate user, create a view as suggested by #ekochergin, and have a synonym "EMPLOYEE" in the application's user schema point to the view in the data owner's schema.
If the application is connecting as the data owner, your options are much more limited. Renaming the table and replacing it with a view as suggested would be the easiest option. If you've got a lot of money to invest in Oracle's Database Application Firewall appliance you could also modify the query in-flight with a security policy there.
You might needed to rename employee table to somewhat like "EMP_TABLE" and create a view named "EMPLOYEE" using
create view employee as select * from emp_table where currently_employed = 'YES';
Please test it against a test instance before implementing on live
Use the SQL Translation Framework if you only need to convert a small number of statements. If you need to modify many statements then you should look into the options described in the other answers, such as Virtual Private Database, views, or synonyms.
For this sample schema:
create table employee
(
employee_id number,
hire_date date,
currently_employed varchar2(3)
);
insert into employee values(1, sysdate, 'NO');
insert into employee values(1, sysdate, 'YES');
commit;
Create the following translator profile and then create the specific translation:
begin
dbms_sql_translator.create_profile('EMPLOYEE_TRANSLATOR_PROFILE');
dbms_sql_translator.register_sql_translation
(
profile_name => 'EMPLOYEE_TRANSLATOR_PROFILE',
sql_text => q'[SELECT * FROM EMPLOYEE WHERE HIRE_DATE > (SYSDATE - 1) order by employee_id]',
translated_text => q'[SELECT * FROM EMPLOYEE WHERE HIRE_DATE > (SYSDATE - 1) and Currently_employed = 'YES' order by employee_id]'
);
end;
/
The translation profile must be enabled in each session. Since you have no control over the application, you can create a logon profile that will automatically run the commands to enable the translation:
--Logon trigger that enables profiles.
--I'm not sure why, but you must create this trigger as SYS.
create or replace trigger sys.logon_trg
after logon on database
--Add your username here:
when (user in ('JHELLER'))
begin
execute immediate 'alter session set sql_translation_profile = jheller.employee_translator_profile';
execute immediate q'[alter session set events = '10601 trace name context forever, level 32']';
end;
/
Now, when the application runs the original query that would normally return two rows, it will run the second query that only returns one row:
SQL> SELECT * FROM EMPLOYEE WHERE HIRE_DATE > (SYSDATE - 1) order by employee_id;
EMPLOYEE_ID HIRE_DATE CUR
----------- --------- ---
1 12-FEB-21 YES
But be careful of tiny syntax changes that will prevent the translation. For example, if SELECT is changed to select, the query will not be replaced and will return two rows again:
SQL> select * FROM EMPLOYEE WHERE HIRE_DATE > (SYSDATE - 1) order by employee_id;
EMPLOYEE_ID HIRE_DATE CUR
----------- --------- ---
1 12-FEB-21 YES
1 12-FEB-21 NO

Is there any way to find the base type of object for which the synonym is created in Oracle 12c?

CREATE SYNONYM office
FOR SEQ001;
I need some system table/any other way that gives me information that SEQ001 is sequence .
In short I need a query that enlist synonyms only created for synonym objects and no other objects.
That would be something like this:
SQL> create sequence seq001;
Sequence created.
SQL> create synonym syn_se for seq001;
Synonym created.
SQL> select s.synonym_name, o.object_name, o.object_type
2 from user_synonyms s join user_objects o on o.object_name = s.table_name;
SYNONYM_NAME OBJECT_NAME OBJECT_TYPE
--------------- --------------- -------------------
SYN_SE SEQ001 SEQUENCE
SQL>
Now, you can apply different filters to it, e.g. where o.object_type = 'SEQUENCE' to see only synonyms related to sequences.
To list all synonyms that reference other synonyms use the dictionary view ALL_SYNONYMS and check if the synonym definition correspond to an other synonym.
Example
The first synonym reference a sequence, the two other reference a synonym.
The query shows the two "nested" synonyms.
create sequence seq001;
create synonym syn001 for seq001;
create synonym syn002 for syn001;
create synonym syn003 for syn002;
select OWNER, SYNONYM_NAME
from all_synonyms
where (TABLE_OWNER, TABLE_NAME) in
(select OWNER, SYNONYM_NAME from all_synonyms)
;
OWNER SYNONYM_NAME
---------- ------------
OOO SYN002
OOO SYN003
The view ALL_SYNONYMS shows all synonyms that your user has a granted access. There is also a dictionary view DBA_SYNONYMS showing all existing synonyms, but you'll need extra privilege to access it.

Create public synonyms for table and sequence in oracle

I need to create public synonyms for sequence.Could you please suggest how to create synonyms for sequence in oracle 11g.
Alter script to add constraint:
ALTER TABLE schema.table_name ADD( CONSTRAINT pk PRIMARY KEY(primaryKey_ID));
Sequence:
CREATE SEQUENCE table_name START WITH 1;
According to documentation you can create a public synonym for your sequence in the same way you do for a table:
create public synonym table_name for yourSchema.table_name;
create public synonym sequence_name for yourSchema.sequence_name;

Sqlplus parameters and variables with default values

Problem
I have sql scripts which may use different tablespaces for different database users.
In order to remain flexible with the table creation I'd like to keep only 1 script and apply it to the various users. For that purpose I have something like this:
Tablespaces:
CREATE TABLESPACE MY_TABLESPACE DATAFILE 'MY_TABLESPACE.dat' SIZE 40M ONLINE;
CREATE TABLESPACE MY_INDEXSPACE DATAFILE 'MY_INDEXSPACE.dat' SIZE 40M ONLINE;
And the table creation script:
define default_tablespace = 'MY_TABLESPACE';
define default_indexspace = 'MY_INDEXSPACE';
drop table test_table;
create table test_table ( id number ) tablespace &default_tablespace;
create index my_index on test_table( id) tablespace &default_indexspace;
i. e. I can't set a default tablespace for the user, because the index uses a different tablespace.
Question
Is it possible to override the definition of default_tablespace and default_indexspace depending on e. g. an environment variable?
Something like:
define default_tablespace = isEnviromentVariableSet( 'OTHER_TABLESPACE') ? getEnvironmentVariable( OTHER_TABLESPACE) : 'MY_TABLESPACE';
That way I could use different tablespaces whenever I invoke the script externally by some utility and at the same time I could keep the default tablespace.
Thank you very much for the help!
In DDL operation (create, drop, etc.) u can't use variables.
Easy way is use pl/sql anonymous block like this.
declare
my_tabable_space varchar2(100) default 'my_some_tablespace';
other_tablespace varchar2(100);
begin
DBMS_SYSTEM.get_env('OTHER_TABLESPACE',other_tablespace);
if other_tablespace is not null then
my_tabable_space := other_tablespace ;
end if;
execute immediate 'create table test_table ( id number ) tablespace' || my_tabable_space;
end;
/
and for select ENV variable u can use DBMS_SYSTEM.get_env ('NAME of VARIABLE', my_variable) but this package need DBA right (i think.. :-) )

Managing Oracle Synonyms

I was reading this article:
Managing Oracle Synonyms
Regarding the order of preference, when it come to resolving an object name to the actual object, it says:
Local objects will always be accessed first.
If a local object does not exist, the object with a private synonym will be accessed.
If a private synonym does not exist or the object does not exist, then the public synonym will be used.
I was wondering if the public objects are missing in this order somehow?
E.g. if user BOB queries
select * from FOOBAR
and there is no BOB.FOOBAR in dba_tables/views but PUBLIC.FOOBAR.
Does Oracle resolve it to PUBLIC.FOOBAR or will it check for synonyms first?
Thank you.
In your example, FOOBAR is almost certainly a public synonym. There is no PUBLIC schema but PUBLIC is listed as the owner of a public synonym.
If I create a new public synonym
SQL> create public synonym pub_syn_emp
2 for scott.emp;
Synonym created.
the owner of that synonym ends up being PUBLIC
SQL> ed
Wrote file afiedt.buf
1 select object_name, owner, object_type
2 from dba_objects
3* where object_name = 'PUB_SYN_EMP'
SQL> /
OBJECT_NAME OWNER OBJECT_TYP
-------------------- ---------- ----------
PUB_SYN_EMP PUBLIC SYNONYM
In addition, item #3 does not appear to be correct. If there is a private synonym that points to a non-existent object and a public synonym that points to a valid object, the private synonym still takes precedence. You'll just get an error when Oracle tries to resolve the private synonym to an actual object.
SQL> create synonym syn_emp for scott.no_such_table;
Synonym created.
SQL> create public synonym syn_emp for scott.emp;
Synonym created.
SQL> select * from syn_emp;
select * from syn_emp
*
ERROR at line 1:
ORA-00980: synonym translation is no longer valid
At least up to 10g, PUBLIC is not a real user. You cannot create objects in the "Public schema":
SQL> CREATE TABLE public.foobar (id integer);
CREATE TABLE public.foobar (id integer)
ORA-00903: invalid table name
SQL> CREATE TABLE system.foobar (id integer);
Table created
SQL>
If you run this query:
SELECT object_name
FROM dba_objects
WHERE owner='PUBLIC'
AND object_type IN ('TABLE', 'VIEW');
You can answer the question about pre-defined tables/views in the PUBLIC "schema".

Resources