Find all index that needs to be rebuilt - oracle

I have been searching for a way to find all the indices that needs to be re-built. But couldn't find a syntax on the web.
Is there a syntax to find the same?

It is unusable. Have a look at the following example:
SQL> create table test (id number);
Table created.
SQL> create index i1t on test (id);
Index created.
Make the index unusable:
SQL> alter index i1t unusable;
Index altered.
SQL> select index_name from user_indexes where status = 'UNUSABLE';
INDEX_NAME
------------------------------
I1T
Rebuild it and check its status again:
SQL> alter index i1t rebuild;
Index altered.
SQL> select index_name from user_indexes where status = 'UNUSABLE';
no rows selected
SQL>
Of course, you wouldn't rebuild them manually - write a script to do it for you. For example:
SQL> set serveroutput on;
SQL> begin
2 for cur_r in (select index_name from user_indexes
3 where status = 'UNUSABLE'
4 )
5 loop
6 dbms_output.put_line('Rebuilding index ' || cur_r.index_name);
7 execute immediate 'alter index ' || cur_r.index_name || ' rebuild';
8 end loop;
9 end;
10 /
Rebuilding index I2T
Rebuilding index I1T
PL/SQL procedure successfully completed.
SQL>

Related

Update second column

I have a table "TEST_TABLE" with two columns TABLE_NAME and RECORD_COUNT.
enter image description here
We want to update the column RECORD_COUNT by taking the total records in table specified in TABLE_NAME.
You could do this with dynamic SQL but why be complicated?
Create a view
Create view my_tables as
Select
'table_1' as "table name",
count(*) as "rows"
From table_1
Add the following for each table
Union all
Select 'table_2',count(*) From table_2
You can then use the view like a table:
Select * from my_tables;
OK, but - why wouldn't you use information Oracle already provides for you? You should regularly gather statistics anyway, so:
SQL> execute dbms_stats.gather_schema_stats(ownname => 'SCOTT', estimate_percent => null);
PL/SQL procedure successfully completed.
and then fetch num_rows from user_tables:
SQL> select table_name, num_rows from user_tables where rownum <= 10;
TABLE_NAME NUM_ROWS
-------------------- ----------
EMP 14
DEPT 4
BONUS 0
SALGRADE 5
DUMMY 1
TBL_ERROR 1
AUDIT_TAB 2
SOURCE_DET 3
EXAMPLE 1
FLIGHT 0
10 rows selected.
SQL>
It can't be much worse than your attempt (due to possible frequent changes to tables' contents; inserts and deletes) because you'd collect your own data periodically (how often?) anyway.
If it has to be your way, then you'd use dynamic SQL, looping through all tables in your schema and actually count number of rows:
SQL> create table test_table
2 (table_name varchar2(30),
3 num_rows number);
Table created.
SQL> create or replace procedure p_test as
2 l_cnt number;
3 begin
4 execute immediate 'truncate table test_table';
5 for cur_R in (select table_name from user_tables) loop
6 execute immediate 'select count(*) from ' ||cur_R.table_name into l_Cnt;
7 insert into test_table (table_name, num_rows) values (cur_r.table_name, l_cnt);
8 end loop;
9 end;
10 /
Procedure created.
Running the procedure and viewing the result:
SQL> exec p_test;
PL/SQL procedure successfully completed.
SQL> select * From test_Table where rownum <= 10;
TABLE_NAME NUM_ROWS
-------------------- ----------
EMP 14
DEPT 4
BONUS 0
SALGRADE 5
DUMMY 1
TBL_ERROR 1
AUDIT_TAB 2
SOURCE_DET 3
EXAMPLE 1
FLIGHT 0
10 rows selected.
SQL>
Note that performance will suffer as number of tables and number of rows stored in them grows.
If I were you, I'd go for the first option.

Disable/enable constraints in an Oracle table using a Stored Proc where table name is Parametrized

I would like to create a reusable Stored Procedure which can disable constraints in a table, when that table is passed as a parameter. I created a stored procedure which has the table name hard coded.Could you please help
Create or Replace Procedure Disable_Constraints
as Begin
Declare
V_OWNER VARCHAR2(30);
V_TABLE_NAME VARCHAR2(30);
V_CONSTRAINT_NAME VARCHAR2(30);
CURSOR C IS
select OWNER,TABLE_NAME,CONSTRAINT_NAME
from all_constraints
where table_name='EMP_CONSTRAINTS';
BEGIN
OPEN C;
LOOP
FETCH C INTO V_OWNER,V_TABLE_NAME,V_CONSTRAINT_NAME;
EXIT WHEN C%NOTFOUND;
dbms_utility.exec_ddl_statement ('alter table ' || V_OWNER || '.' || V_TABLE_NAME || ' disable constraint ' || V_CONSTRAINT_NAME);
END LOOP;
CLOSE C;
END;
END DISABLE_CONSTRAINTS;
Thanks,
Khader
For example:
Sample table:
SQL> CREATE TABLE test
2 (
3 id NUMBER CONSTRAINT pkt PRIMARY KEY,
4 name VARCHAR2 (20) CONSTRAINT cht CHECK (name LIKE 'A%')
5 );
Table created.
Procedure:
SQL> CREATE OR REPLACE PROCEDURE p_disc (par_table_name IN VARCHAR2)
2 IS
3 BEGIN
4 FOR cur_r
5 IN (SELECT constraint_name
6 FROM user_constraints
7 WHERE UPPER (table_name) =
8 UPPER (DBMS_ASSERT.sql_object_name (par_table_name)))
9 LOOP
10 EXECUTE IMMEDIATE
11 'alter table '
12 || DBMS_ASSERT.sql_object_name (par_table_name)
13 || ' disable constraint '
14 || cur_r.constraint_name;
15 END LOOP;
16 END;
17 /
Procedure created.
Testing:
SQL> SELECT constraint_name, status FROM user_constraints WHERE table_name = 'TEST';
CONSTRAINT_NAME STATUS
------------------------------ --------
CHT ENABLED
PKT ENABLED
SQL> EXEC p_disc('test');
PL/SQL procedure successfully completed.
SQL> SELECT constraint_name, status FROM user_constraints WHERE table_name = 'TEST';
CONSTRAINT_NAME STATUS
------------------------------ --------
CHT DISABLED
PKT DISABLED
SQL>

How to use a variable to alter a constraint of a table in PL SQL?

I am trying to get the name of a constraint and then alter a table to remove the constraint. The constraint has not been named so I guess I have no other option. Here is what I tried:
DECLARE
the_variable VARCHAR2(20);
BEGIN
SELECT CONSTRAINT_NAME INTO the_variable
FROM all_constraints
WHERE table_name = 'MY_TABLE'
AND SEARCH_CONDITION_VC = 'format IN (''CSV'', ''PDF'')';
END;
The query above seems to work fine, but when I try to alter the table in this way:
ALTER TABLE SOME_TABLE DROP CONSTRAINT the_variable;
I get this error:
SQL Error [6550] [65000]: ORA-06550: line 14, column 1:
PLS-00103: Encountered the symbol "ALTER"
You can't perform DDL like that; has to be dynamic SQL. Here's an example - you need what's written in line #9:
SQL> create table my_table (id number primary key);
Table created.
SQL> declare
2 the_variable varchar2(30);
3 begin
4 select constraint_name
5 into the_variable
6 from all_constraints
7 where table_name = 'MY_TABLE';
8
9 execute immediate 'alter table my_table drop constraint ' || the_variable;
10 end;
11 /
PL/SQL procedure successfully completed.
SQL> select count(*) from all_constraints where table_name = 'MY_TABLE';
COUNT(*)
----------
0
SQL>

How to run a query on different schemes at once

I want to run a query on different schemes to get data and export it. I use the following code
DECLARE
sql_statment VARCHAR2(2000);
BEGIN
FOR c IN (SELECT brchcode FROM brchs) LOOP
sql_statment := 'select distinct ''' || c.brchcode ||''', t.risuid from ' || c.brchcode ||
'.reg_individualacnt_detail t
where t.historytypecode = 60';
EXECUTE IMMEDIATE sql_statment;
END LOOP;
END;
where brchcode is the name of different schemes
I can't see any output. what can I do?
Code you wrote can't work as you have to return the result into something; it is PL/SQL and requires an INTO clause. As you chose to return two values (columns) and multiple rows, that can't be a scalar variable; you could pick ref cursor or a collection, for example.
Here's an example which shows one option.
I'll be using two schemas: SCOTT (current schema) and HR. Both will be having the DEPT table.
As Scott already has it, I'll create one in HR schema and grant access to Scott (otherwise, Scott won't even see it and the procedure (i.e. the function) will fail):
SQL> connect hr/hr
Connected.
SQL> create table dept (deptno number, dname varchar2(10), loc varchar2(10));
Table created.
SQL> insert into dept values (55, 'IT', 'Zagreb');
1 row created.
SQL> grant select on dept to scott;
Grant succeeded.
SQL> commit;
Commit complete.
Back to Scott, to create a table (which contains schema names I'll be selecting from) and a function. I chose to return REF CURSOR; you could return something else, if you want.
SQL> connect scott/tiger
Connected.
SQL> create table brchs (brchcode varchar2(10));
Table created.
SQL> insert into brchs (brchcode)
2 select 'scott' from dual union all
3 select 'hr' from dual;
2 rows created.
SQL> create or replace function f_br
2 return sys_refcursor
3 is
4 l_str varchar2(4000);
5 l_rc sys_refcursor;
6 begin
7 for cur_r in (select brchcode from brchs) loop
8 l_str := l_str ||
9 'union all
10 select ' || chr(39)|| cur_r.brchcode ||chr(39) || ', d.dname
11 from ' || cur_r.brchcode ||'.dept d
12 where d.deptno > 0';
13 end loop;
14
15 l_str := ltrim(l_str, 'union all');
16
17 open l_rc for l_str;
18 return l_rc;
19 end;
20 /
Function created.
SQL>
Finally, testing:
SQL> select f_br from dual;
F_BR
--------------------
CURSOR STATEMENT : 1
CURSOR STATEMENT : 1
'SCOT DNAME
----- --------------
scott ACCOUNTING
scott RESEARCH
scott SALES
scott OPERATIONS
hr IT
SQL>

Execute multiple Oracle SQL statements simultaneously

I have an Oracle database that has 20 very large tables, each with hundreds of partitions. I can compress a table but it takes over 2 hours. This would mean over 40 hours to complete all 20 tables. I would like to run the partition compression simultaneously (1 per table). Because the partitions are added daily I need a utility to generate the "alter table ..." syntax at the time of the run. So far, all I can think of is to create a SQL for each of the 20 tables and their partitions, then run them in 20 SQLPlus sessions.
Is there a better, more automated way to do this?
You could submit several jobs, which will - in turn - run your code simultaneously. Here's an example:
Test tables - I want to modify ID's datatype to VARCHAR2(10)
SQL> create table t1 (id varchar2(2));
Table created.
SQL> create table t2 (id varchar2(2));
Table created.
SQL> create table t3 (id varchar2(2));
Table created.
A procedure which will utilize EXECUTE IMMEDIATE and is called from DBMS_JOB (see below):
SQL> create or replace procedure p_exe (par_what in varchar2) is
2 begin
3 execute immediate par_what;
4 end;
5 /
Procedure created.
Create jobs which will run the ALTER TABLE simultaneously
SQL> declare
2 l_str varchar2(200);
3 l_job number;
4 begin
5 for cur_r in (select 't1' table_name from dual union all
6 select 't2' from dual union all
7 select 't3' from dual)
8 loop
9 l_str := 'alter table ' || cur_r.table_name || ' modify id varchar2(10)';
10 dbms_output.put_line(l_str);
11 dbms_job.submit(l_job,
12 'p_exe(' || chr(39) || l_str || chr(39) ||');',
13 sysdate
14 );
15 commit;
16 end loop;
17 end;
18 /
PL/SQL procedure successfully completed.
Jobs are now running; in a few moments (in my case, as it is a simple one - you'd check that somewhat later), check what's being done:
SQL> desc t1;
Name Null? Type
----------------------- -------- ----------------
ID VARCHAR2(10)
SQL> desc t3;
Name Null? Type
----------------------- -------- ----------------
ID VARCHAR2(10)
SQL> desc t3;
Name Null? Type
----------------------- -------- ----------------
ID VARCHAR2(10)
SQL>

Resources