oracle set public synonym all table or other object? - oracle

I have productionDB and testDB.ProductionDB have synonym for tables.And now i want to create synonym for all tables for testDB.How i can create synonym all of them. I can get list synonym this query
select *
from all_synonyms s
join all_objects o
on s.table_owner = o.owner
and s.table_name = o.object_name
where s.table_owner = 'XYZ'

Try the following query:
SELECT CAST(dbms_metadata.get_ddl(object_type => 'SYNONYM',
name => a.synonym_name,
SCHEMA => a.owner) AS VARCHAR2(4000))
FROM ALL_SYNONYMS a;
Share and enjoy.

This is a starter script - it writes sql as output. Run it, READ the output first. Uncomment the last line when you think it is correct - it has to be run with privilege.
set pages 0
set feed off
set linesize 180
set trimspool on
spool syn.sql
select 'CREATE PUBLIC SYNONYM ' || SYNONYM_NAME | ' FOR ' ||
TABLE_OWNER || '.' || TABLE_NAME || ';'
from ALL_SYNONYMS
where DB_LINK is NULL;
select 'CREATE PUBLIC SYNONYM ' || SYNONYM_NAME | ' FOR ' ||
TABLE_OWNER || '.' || TABLE_NAME || '#' || DB_LINK || ';'
from ALL_SYNONYMS
where DB_LINK is NOT NULL;
spool off
-- uncomment after it has been tested
--#syn.sql
If testDB was created using a PROD export then why are the synonyms all missing? Something is very wrong here. OR I am missing something.

Related

Oracle plsql switch case and sqlplus spool

The following query runs in an error at the THAN statement. Is it possible to use a select in the THAN statement? Any ideas on how to make it work?
SET SERVEROUTPUT ON
SET TERMOUT OFF
SET ECHO OFF
SET FEEDBACK OFF
SET LINESIZE 140
SET PAGESIZE 0
exec dbms_output.enable(NULL);
SPOOL C:\test\user.sql
BEGIN
SELECT DISTINCT version,
CASE
WHEN version = '12.1.0.2.0'
THEN
dbms_output.put_line(''select' || 'Alter user ' || username || ' identified by values ' || '''EE3FD1E715941451''' || ';''); from DBA_USERS_WITH_DEFPWD;
ELSE
dbms_output.put_line(''select' || 'Alter user ' || username || ' identified by values ' || '''Invalid Password''' || ';''); from DBA_USERS_WITH_DEFPWD;
FROM PRODUCT_COMPONENT_VERSION;
END;
SPOOL OFF
Edit:
Code which is working looks like this:
spool c:/test/user.sql
select 'Alter user ' || username || ' identified by values ' || '''Invalid Password''' || ';'
from DBA_USERS_WITH_DEFPWD;
spool off
Spool output example:
Alter user GSMUSER identified by values 'Invalid Password';
Alter user MDSYS identified by values 'Invalid Password';
Alter user OLAPSYS identified by values 'Invalid Password';
Alter user LBACSYS identified by values 'Invalid Password';
The script is not working with new Oracle DB Versions. Since Oracle 12.1.0.2.0 it’s not possible to set the password to an invalid password. I need to build in version identification for this issue. All Oracle Databases with a version below 12.1.0.2.0 should be treated with the old script and the passwords should be set to “invalid password”. All newer versions should get some kind of standard password for now.
Maybe you need something like this:
...
DECLARE
vVersion varchar2(100);
BEGIN
/* get the version */
SELECT DISTINCT version
into vVersion
from PRODUCT_COMPONENT_VERSION;
--
/* loop through users */
for i in ( select * from DBA_USERS_WITH_DEFPWD) loop
/* print a different statement, based on vVersion, for the current user */
if ( vVersion = '12.1.0.2.0' ) then
dbms_output.put_line('Alter user ' || i.username || ' identified by values ' || '''EE3FD1E715941451''' || ';');
else
dbms_output.put_line('Alter user ' || i.username || ' identified by values ' || '''Invalid Password''' || ';');
end if;
end loop;
END;
...
Another version which solves the problem without PL/SQL and correct spool:
SET TERMOUT OFF
SET ECHO OFF
SET LINESIZE 140
SET FEEDBACK OFF
SET PAGESIZE 0
SPOOL user.sql
SELECT 'alter user ' || username || ' identified by values '''
|| CASE
WHEN b.version = '12.1.0.2.0' THEN '462368EA9F7AD215'
ELSE 'Invalid Password'
END
|| ''';'
FROM DBA_USERS_WITH_DEFPWD a,
(SELECT VERSION
FROM PRODUCT_COMPONENT_VERSION
WHERE UPPER (product) LIKE '%DATABASE%') b;
SPOOL OFF
#user.sql
If it's not possible to use PL/SQL:
SET TERMOUT OFF
SET ECHO OFF
SET LINESIZE 140
SET FEEDBACK OFF
SET PAGESIZE 0
spool user.sql
SELECT 'Alter user '
|| A.USERNAME
|| ' identified by values '
|| '''EE3FD1E715941451'''
|| ';'
FROM DBA_USERS_WITH_DEFPWD a,
(SELECT DISTINCT version
FROM PRODUCT_COMPONENT_VERSION) b
WHERE version = '12.1.0.2.0'
UNION ALL
SELECT 'Alter user '
|| A.USERNAME
|| ' identified by values '
|| '''Invalid Password'''
|| ';'
FROM DBA_USERS_WITH_DEFPWD a,
(SELECT DISTINCT version
FROM PRODUCT_COMPONENT_VERSION) b
WHERE version != '12.1.0.2.0';
spool off
#user.sql

How to format code to '' || chr(10) || using plsql developer

I need to convert a large amount of code into the below format:
'MERGE INTO employees emp' || chr(10) ||
'USING (SELECT * FROM (SELECT (SELECT VALUE
FROM departments
WHERE CNTRY_CDE = ''100''
AND NAME = ''Scott'') BATCH_ID, SUBJECT_ID,' || chr(10) ||
as this code is being inserted in to a table as clob data.
Is there any way to do it?
The above given code is just the sample I have.
If I understand correctly you have an SQL statement which looks something like
'MERGE INTO employees emp USING (SELECT * FROM (SELECT (SELECT VALUE FROM departments WHERE CNTRY_CDE = ''100'' AND NAME = ''Scott'') BATCH_ID, SUBJECT_ID,'
and you want it to look like
'MERGE INTO employees emp' || chr(10) || 'USING (SELECT * FROM (SELECT (SELECT VALUE FROM departments WHERE CNTRY_CDE = ''100'' AND NAME = ''Scott'') BATCH_ID, SUBJECT_ID,' || chr(10) ||
Despite my misgivings about the practicality of this, I suppose one way to accomplish it is something like the following:
declare
strOldstmt VARCHAR2(2000) := 'MERGE INTO employees emp USING (SELECT * FROM (SELECT (SELECT VALUE FROM departments WHERE CNTRY_CDE = ''100'' AND NAME = ''Scott'') BATCH_ID, SUBJECT_ID,';
strNewstmt VARCHAR2(2000);
begin
-- Test statements here
DBMS_OUTPUT.PUT_LINE('strOldstmt=''' || strOldstmt || '''');
strNewstmt := REPLACE(strOldstmt, 'USING', ''' || CHR(10) || '' USING') || ''' || CHR(10) || ';
DBMS_OUTPUT.PUT_LINE('strNewstmt=''' || strNewstmt || '''');
end;
The problem here is that this is very specific to this particular statement, which may not work with other statements; however, it does work for the example you've given and I'm not able to guess at what your more general requirements might be.
Best of luck.

UPDATE statements in oracle pl/sql loop with tablenames as parameters

I have a requirement where I need to run set of UPDATE statements in a for loop.
In the cursor there is a column called PROPERTY_ID which is a number and there are many tables
that have this number appended.
For ex: SELECT * FROM PC_ORG_EXT_111(where 111 is the property_id)
This is the code and it's throwing error.
Can anyone assist me if I'm missing something here.
SET SERVEROUTPUT ON SIZE 1000000
SET LINESIZE 1000
SET PAGESIZE 0
DECLARE
V_PROP_ID VARCHAR(200);
V_CNT NUMBER(25);
V_SQL_STRING VARCHAR2(500);
CURSOR CUR_CON
IS
SELECT * FROM PRE_CONVERSION_UNMERGE_LIST;
BEGIN
FOR REC_CON IN CUR_CON
LOOP
V_PROP_ID := 'PROPARCH.PC_ORG_EXT_' || REC_CON.PROPERTY_ID;
dbms_output.put_line('Property Table Name ' || V_PROP_ID);
EXECUTE IMMEDIATE 'select COUNT(1) from ' ||V_PROP_ID;
EXECUTE IMMEDIATE '
UPDATE SIEBEL.S_ACCNT_POSTN
SET OU_EXT_ID = ' || REC_CON.VALID_SURVIVIR_REC ||'
WHERE OU_EXT_ID = ' || REC_CON.INVALID_SURVIVOR_REC||'
AND OU_EXT_ID IN (SELECT ISAC_ROW_ID
FROM ' || V_PROP_ID || '
WHERE INTEGRATION_ID = '||REC_CON.DELPHI_ID||')
AND POSITION_ID NOT IN
(SELECT POSITION_ID
FROM SIEBEL.S_ACCNT_POSTN
WHERE OU_EXT_ID = '||REC_CON.VALID_SURVIVIR_REC||')';
END LOOP;
END;
Error says :
ORA-00933: SQL command not properly ended
ORA-06512: at line 20
Also let me know if there's a better way of doing it.
Thanks,
Please try this! - Single Quotes has to be Used with escape characters!
EXECUTE IMMEDIATE '
UPDATE SIEBEL.S_ACCNT_POSTN
SET OU_EXT_ID = ''' || REC_CON.VALID_SURVIVIR_REC ||'''
WHERE OU_EXT_ID = ''' || REC_CON.INVALID_SURVIVOR_REC||'''
AND OU_EXT_ID IN (SELECT ISAC_ROW_ID
FROM ' || V_PROP_ID || '
WHERE INTEGRATION_ID = '''||REC_CON.DELPHI_ID||''')
AND POSITION_ID NOT IN
(SELECT POSITION_ID
FROM SIEBEL.S_ACCNT_POSTN
WHERE OU_EXT_ID = '''||REC_CON.VALID_SURVIVIR_REC||''')';

Query to find all empty tables

Considering that I have a Schema named SBST
I want to find all empty tables list in this SBST Schema. Is there any PL/SQL procedure to find that. I found few. But those were using user tables where I was not able specify the Schema name SBST.
I was using this
select table_name from dba_tables where owner ='SBST'
having count(*)=0 group by table_name
What's wrong in the above query?
You can fire below query to find the list of tables haveing no data
select * from ALL_TABLES
where owner ='SBST'
AND NUM_ROWS = 0;
Similar to #shareef's answer, but using dynamic SQL to avoid having to create the temporary .sql file. You'll need dbms_output to be visible, e.g. with set serveroutput on in SQL*Plus - don't know about Toad.
declare
cursor c(p_schema varchar2) is
select 'select ''' || table_name || ''' from ' ||
p_schema ||'.' || table_name || ' where rownum < 2 ' ||
' having count(*) = 0' as query
from all_tables
where owner = p_schema
order by table_name;
l_table all_tables.table_name%TYPE;
begin
for r in c('SBST') loop
begin
execute immediate r.query into l_table;
exception
when no_data_found then continue;
end;
dbms_output.put_line(l_table);
end loop;
end;
/
Using all_tables seems more useful than dba_tables here so you know you can select from the tables it lists. I've also included the schema in the from clause in case there other users have tables with the same name, and so you can still see it if you're connected as a different user - possibly avoiding synonym issues too.
Specifically what's wrong with your query... you've got the having and group by clauses the wrong way around; but it will always return no data anyway because if SBST has any tables then count (*) from dba_tables must be non-zero, so the having always matches; and if it doesn't then, well, there's no data anyway so there's nothing for the having to match against. You're counting how many tables there are, not how many rows are in each table.
the straight forward answer is
select 'select ''' || table_name || ''' from ' || table_name || '
having count(*) = 0;' from dba_tables where owner='SBST';
EXPLANATION
You can run this... it will just output the table names of those having no rows:
assuming you use sqlplus but i used toad to test it
and it worked very well
set echo off heading off feedback off lines 100 pages 0;
spool tmp.sql
select 'select ''' || table_name || ''' from ' || table_name || '
having count(*) = 0;' from user_tables where owner='SBST';
spool off;
#tmp.sql
If you open the "tmp.sql" file, you'll see for all tables....
select 'PERSONS' from PERSONS having count(*) = 0;
select 'DEPARTMENT' from DEPARTMENT having count(*)=0;
in your case you want a schema and schema is a user right the above code if you connect with the user SBST but if you connect with other then you have to use DBA_TABLES and assign owner attribute to SBST
USER_TABLES is tables which you own ALL_TABLES is tables which own,
and tables owner by other users, which you have been granted excplicit
access to DBA_TABLES is all tables in the database
like this
set echo off heading off feedback off lines 100 pages 0;
spool tmp.sql
select 'select ''' || table_name || ''' from ' || table_name || '
having count(*) = 0;' from dba_tables where owner='SBST';
spool off;
#tmp.sql
All three are views of the underlying SYS tables, but the USER_ and
ALL_ views joing in your username/security info to limit the results
**SUMMARY **
PLEASE JUST RUN THIS QUERY
select 'select ''' || table_name || ''' from ' || table_name || '
having count(*) = 0;' from dba_tables where owner='SBST';
If table stats are up to date then you could use:
SELECT TABLE_NAME
FROM ALL_TAB_STATISTICS
WHERE (OWNER = 'ME')
AND (NUM_ROWS = 0);

Replace CHAR with VARCHAR2

How can I replace CHAR with VARCHAR2 in all tables in a schema?
Note: I'm content with a query that returns the ALTER TABLE statements so I can save the script and run it again.
select 'ALTER TABLE "' || owner || '"."' || table_name
|| '" MODIFY ("' || column_name
|| '" VARCHAR2(' || data_length || '));'
from all_tab_columns tc
where data_type = 'CHAR'
and owner = :schemaname
and exists (
select 1
from all_tables t
where tc.owner = t.owner
and tc.table_name = t.table_name
);

Resources