DROP and CREATE index at the same time - sql

We have table owner name and index owner name mismatch. We need to drop the index as well the constraints associated with it and recreate the same in the particular schema to match index owner and table owner name. We have different column count for each index varying from 1 to 4.
I need to create a procedure for dropping n recreating at the same time.
declare
total number(10);
table_name varchar2(255);
index_name varchar2(255);
column_name varchar2(255);
begin
select a.table_name, a.index_name,count(a.column_name) into table_name, index_name,total
from all_ind_columns a, all_indexes b where a.index_name = b.index_name
and b.table_owner = 'SIM'and b.owner like 'TIM'
group by a.table_name,a.index_name
order by a.table_name,a.index_name,count(a.column_name);
select c.column_name into column_name from all_ind_columns c,all_indexes d
where c.index_name=d.index_name
and d.table_owner='SIM' and d.owner like 'TIM';
for i in (select a.table_name, a.index_name,count(a.column_name) from all_ind_columns a, all_indexes b where a.index_name = b.index_name
and b.table_owner = 'SIM'and b.owner like 'TIM'
group by a.table_name,a.index_name
order by a.table_name,a.index_name,count(a.column_name))
loop
If i.count(a.column_name)=1 then
DBMS_OUTPUT.PUT_LINE ('Create index'||index_name|| 'on' ||table_name||'('||Column_name||')');
else total>=2
then
DBMS_OUTPUT.PUT_LINE ('Create index'||index_name|| 'on' ||table_name||'('||Column_name,Column_name||')');
end if;
end loop;
end;

DBMS_METADATA is the official way to regenerate object DDL. It's usually better than manually creating DDL statements. There are hundreds of options for creating indexes, DBMS_METADATA.GET_DDL is the only way to ensure you accurately recreate the object.
declare
v_index_ddl clob;
begin
for indexes_in_wrong_schema in
(
select table_name, index_name
from all_indexes
where table_owner = 'SIM' and owner like 'TIM'
) loop
v_index_ddl := dbms_metadata.get_ddl('INDEX',
indexes_in_wrong_schema.index_name, 'TIM');
--Or replace these with "execute immediate" to run instead of print.
dbms_output.put_line('drop index TIM.'||
indexes_in_wrong_schema.index_name);
dbms_output.put_line(replace(v_index_ddl, '"TIM"', '"SIM"'));
end loop;
end;
/
Privileges
DBMS_METADATA requires you either have the SELECT_CATALOG_ROLE or are executing as the schema owner. Ask a DBA or other privileged user if they can grant you that role. Or convert the above PL/SQL block into a function, install the function on the owner's schema, and then grant execute on new_function to your_user;.

Related

oracle - concatenate in select for drop, create, grant - lost in ''''

I am new to Oracle database, got a task to write several selects, but I do not get somethow principle, how it works (or better to say does not work). Could you please help me to find a mistake and probably you have a link to some info or converter that helps such writings.
v_sql := 'SELECT ''DROP TABLE ''||object_name||'' as
select *
FROM all_objects
WHERE object_name LIKE '''%''|| v_date ||''%'''
and object_type = ''TABLE''
and owner =''||v_owner||''';
Are you trying to generate DROP statements for a specific user? Start with the below anonymous block and add to it.
--Generate DROP statements for all tables for a user.
declare
v_owner varchar2(128) := user;
begin
for objects in
(
select distinct 'DROP TABLE "'||owner||'"."'||object_name||'"' v_sql
from all_objects
where object_type = 'TABLE'
and owner = v_owner
order by v_sql
) loop
dbms_output.put_line(objects.v_sql);
end loop;
end;
/

How to find to which schema or procedure, table and column a particular value belongs to?

I have a 9 digit number, say "234234234", is there a way to find or check its appearance in my database, like in which particular schema or procedure does it fall? and list out all the tables and columns which has that value in pl/sql developer
This query only searches in stored objects that user is allowed to access (procedure, function, package, ...). You could refer to this
Not sure if there is one way to search for that value in all database table.
SELECT *
FROM all_source
WHERE text LIKE '%234234234%';
--AND owner = 'SCHEMA_NAME';
The below block identifies the given string's presence across all the tables in your DB.
declare
num_rows number;
sql_text varchar2(250);
sql_info varchar2(100);
begin
dbms_output.enable(1000000);
for x in (select table_name, column_name from dba_tab_columns
where data_type in ('VARCHAR','VARCHAR2','CHAR')
and owner <> 'SYSTEM')
loop
sql_text:='select count(*) into :num_rows from SYSTEM.'||x.table_name||' where '||x.column_name||' like ''%234234234%''';
-- dbms_output.put_line (sql_text);
execute immediate sql_text into num_rows;
if num_rows>0
then
sql_info:='Table: '||x.table_name||' contains the string';
dbms_output.put_line (sql_info);
end if;
end loop;
end;
/

ORACLE SQL: Looping over table

I have a table that contains a list of table names.
I would like to search each of these tables one by one to see if they contain a particular element (the primary key, specified at the start of the script).
I would like to return a list of all of the tables that this element is present in (ideally distinct).
I'm fairly new to this PL/SQL "not just a query" stuff. so i apologise in advance for the attrocious attempt you are about to see, but hopefully it illustrates what i'm going for:
PROCEDURE CHECK_FOR_ELEMENTS
BEGIN
DECLARE
ELEMENT_KEY varchar(5):=X78ehryfk;
RNUM_MAX int :=167;
----create output table for script
create or replace table ALL_TABLES CONTAINING_&ELEMENT_KEY
(ELEMENT_KEY VARCHAR(255),
TABLE_NAME varchar(255))
/
commit;
---begin loop over rnum;
FOR rnum_counter in 1..&RNUM_MAX
LOOP
--define this statement as variable TABLE_NAME_VAR
select table_name from (select * from (select table_name, rownum as rnum
from all_tables
where owner = 'RMS'
and table_name like 'ABC%'
and table_name not like '%STG'
and table_name not like '%BKP'
and num_rows>0
order by num_rows desc)
where rnum = rnum_counter
)INTO TABLE_NAME_VAR
;
----run below to collect row, if it exists, from table being searched
SQL_STMT:='INSERT INTO ALL_TABLES CONTAINING_&ELEMENT_KEY
SELECT distinct key,'||TABLE_NAME_VAR||' as UMF from
'||TABLE_NAME_VAR||
' where key like 'ELEMENT_KEY-%'
execute immediate SQL_STMT;
commit;
---insert row into table created for output
END LOOP
---loop over all tables
END;
The main error message i get is that TABLE_NAME_VAR is not a valid table name within the dynamic SQL statement. I've googled a bit and i now understand you can't use variables to input table names in this way.
Any help is greatly appreciated!
Thankyou!
Here, I tried to clean it up for you. Let me know if you still get errors.
create or replace PROCEDURE CHECK_FOR_ELEMENTS is
ELEMENT_KEY varchar2(14):='X78ehryfk';
RNUM_MAX int :=167;
TABLE_NAME_VAR varchar2(30);
SQL_STMT varchar2(4000);
BEGIN
----create output table for script
begin
execute immediate 'drop table ALL_TABLES_WITH_' || element_key;
exception when others then null;
end;
execute immediate 'create table ALL_TABLES_WITH_' || element_key || '
(ELEMENT_KEY VARCHAR2(255), -- does this need to be 255 characters?
TABLE_NAME varchar2(30))';
--- implicit cursor loop
FOR rnum_row in (select table_name, rownum as rnum
from all_tables
where owner = 'RMS'
and table_name like 'ABC%'
and table_name not like '%STG'
and table_name not like '%BKP'
and num_rows>0
order by num_rows desc)
LOOP
if rnum_row.rnum > RNUM_MAX
then exit;
end if;
TABLE_NAME_VAR := rnum_row.table_name;
----run below to collect row, if it exists, from table being searched
SQL_STMT:='INSERT INTO ALL_TABLES_WITH_' || element_key || '
(ELEMENT_KEY, TABLE_NAME)
SELECT distinct key, :1 as UMF from
'||TABLE_NAME_VAR||
' where key like :2';
execute immediate SQL_STMT using TABLE_NAME_VAR, element_key || '-%';
---insert row into table created for output
END LOOP;
commit;
---loop over all tables
END CHECK_FOR_ELEMENTS;
/

Copy tables form schema in another schema in Oracle

I want to write a procedure or a cursor.
Input data -- NAME OWNER.
We know name (OWNER) AND from table ALL_OBJECTS
Take the name of the table.
Tables > 30.
How to write correctly ?
CREATE OR REPLACE PROCEDURE USER_NAME
(
v_USER VARCHAR2
)
AS
v_sysdate VARCHAR2(10) := to_char(SYSDATE ,'MMDDYYYY');
v_table_name VARCHAR2(50);
BEGIN
SELECT
TABLE_NAME INTO v_table_name
FROM
ALL_OBJECTS F -- Table with two columnsю. OWNER AND NAME TABLES
WHERE
F.OWNER = v_USER;
--Name of tables and owner ALL_OBJECTS
EXECUTE IMMEDIATE 'CREATE TABLE USER_BANCU.'||v_USER||'_'||v_table_name||'__'||v_sysdate||to_char(sysdate,'HH24_MI_SS')||' AS
SELECT *
FROM '||v_USER||'.'||v_table_nam;
COMMIT;
END;
/
Try DBMS_METADATA_GET_DDL.
enter link description here

Truncating table before dynamic SQL with looping variables inside of one function

I have a function that loops through specific schema names and inserts data into a table. I would like to be able to truncate said table before the insert loop occurs. I've tried putting the truncate statement inside of the dynamic query and that caused it to only keep schema's data inside of the table. I also tried declaring it as it's own variable and then executing the statement separately from the looping statement -- but that resulted in the same.
So my question is -- Where exactly would I put a truncate table dwh.prod_table_notify statement within this function? So that every time I run this function the table would be truncated and then the insert would properly loop through each schema being returned from the FOR statement.
NOTE: I'm forced to use postgres 8.2
CREATE OR REPLACE FUNCTION dwh.dim_table_notification()
RETURNS void
LANGUAGE plpgsql
AS $function$
Declare
myschema varchar;
sql2 text;
Begin
for myschema in
select distinct table_schema
from information_schema.tables
where table_name in ('dim_loan_type', 'dim_acct_type')
and table_schema NOT LIKE 'pg_%'
and table_schema NOT IN ('information_schema', 'ad_delivery', 'dwh', 'users', 'wand', 'ttd')
order by table_schema
loop
sql2 ='insert into dwh.prod_table_notify
select '''|| myschema ||''' as userid, loan_type_id as acct_type_id, loan_type::varchar(10) as acct_type, loan_type_desc::varchar(50) as acct_type_desc, term_code, 1 as loan_type from '|| myschema || '.' ||'dim_loan_type where term_code is null
union
select '''|| myschema ||''' as userid, acct_type_id, acct_type::varchar(10), acct_type_desc::varchar(50), term_code, 0 as loan_type from '|| myschema || '.' ||'dim_acct_type where term_code is null';
execute sql2;
end loop;
END;
$function$
CREATE OR REPLACE FUNCTION dwh.dim_table_notification()
RETURNS void LANGUAGE plpgsql AS
$func$
DECLARE
myschema text;
BEGIN
-- truncate simply goes here:
TRUNCATE dwh.prod_table_notify;
FOR myschema IN
SELECT quote_ident(table_schema)
FROM information_schema.tables
WHERE table_name IN ('dim_loan_type', 'dim_acct_type')
AND table_schema NOT LIKE 'pg_%'
AND table_schema NOT IN
('information_schema', 'ad_delivery', 'dwh', 'users', 'wand', 'ttd')
ORDER BY table_schema
LOOP
EXECUTE '
INSERT INTO dwh.prod_table_notify
(userid, acct_type_id, acct_type, acct_type_desc, loan_type)
SELECT '''|| myschema ||''', loan_type_id, loan_type::varchar(10)
, loan_type_desc::varchar(50), term_code, 1 AS loan_type
FROM '|| myschema || '.dim_loan_type
WHERE term_code IS NULL
UNION ALL
SELECT '''|| myschema ||''' AS userid, acct_type_id, acct_type::varchar(10)
, acct_type_desc::varchar(50), term_code, 0 AS loan_type
FROM '|| myschema || '.dim_acct_type
WHERE term_code IS NULL';
END LOOP;
END
$func$
Are you sure, you can actually use TRUNCATE? Quoting the manual for 8.2:
TRUNCATE cannot be used on a table that has foreign-key references from other tables, unless all such tables are also truncated in the same command.
If tables are small, DELETE is faster than TRUNCATE to begin with:
DELETE FROM dwh.prod_table_notify;
You have to sanitize identifiers! Use quote_ident(), also available in pg 8.2.
No point in using DISTINCT here.
Provide a column definition list for your INSERT. Else it can break in confusing ways, when you change the table later.
If rows in the two legs of the SELECT are unique, use UNION ALL instead of UNION. No point in trying to fold duplicates.