Need to iterate the result and then execute immediate each result using pl/sql - sql

So I have this query:
select 'alter index '||a.index_owner||'.'||a.index_name|| ' rebuild partition '||a.partition_name
from dba_ind_partitions a
where a.index_name in ('IDX_PI_T_BSCS_CONTRACT_HISTOR2', 'IDX_PI_T_BSCS_CONTRACT_HISTOR3', 'IDX_PI_T_BSCS_RATEPLAN_HIST_C1')
and a.status = 'UNUSABLE'
And I need to iterate over the result and then execute immediate each statement.

Basically, you'd convert SELECT you wrote into a cursor FOR loop and execute it.
Here's how; I can't test it, but - if SELECT returns what you want, that's the way to do it.
SQL> show user
USER is "SYS"
SQL> BEGIN
2 FOR cur_r
3 IN (SELECT 'alter index '
4 || a.index_owner
5 || '.'
6 || a.index_name
7 || ' rebuild partition '
8 || a.partition_name
9 as l_alter
10 FROM dba_ind_partitions a
11 WHERE a.index_name IN ('IDX_PI_T_BSCS_CONTRACT_HISTOR2',
12 'IDX_PI_T_BSCS_CONTRACT_HISTOR3',
13 'IDX_PI_T_BSCS_RATEPLAN_HIST_C1')
14 AND a.status = 'UNUSABLE')
15 LOOP
16 EXECUTE IMMEDIATE cur_r.l_alter;
17 END LOOP;
18 END;
19 /
PL/SQL procedure successfully completed.
SQL>

Related

I'm trying to create a procedure for deleting rows how many rows inputted in special table, but I can't use table in input parameters

CREATE OR REPLACE PROCEDURE delete_rows (table_name IN USER_TABLES.table_name%type, row_count in number)
IS
BEGIN
execute immediate 'delete from'||table_name||' where rowid in (select rowid from table_name fetch first Row_count rows only)';
dbms_output.put_line(sql%rowcount);
END;
/
I get this error:
PLS-00357: Table View Or Sequence reference 'EMPLOYEES' not allowed in this context
When working with dynamic SQL, it is almost ALWAYS useful to prepare statement you'll execute, review it and - once you're satisfied with it - actually execute it. Here's what your code is trying to do:
SQL> set serveroutput on
SQL> CREATE OR REPLACE PROCEDURE delete_rows
2 (table_name IN USER_TABLES.table_name%type,
3 row_count in number)
4 IS
5 l_str varchar2(200);
6 BEGIN
7 l_str := 'delete from'||table_name||' where rowid in ' ||
8 '(select rowid from table_name fetch first Row_count rows only)';
9 dbms_output.put_line(l_str);
10 -- execute immediate l_str;
11 dbms_output.put_line(sql%rowcount);
12 END;
13 /
Procedure created.
SQL> exec delete_rows('test', 2);
delete fromtest where rowid in (select rowid from table_name fetch first
Row_count rows only)
PL/SQL procedure successfully completed.
SQL>
What do you think, can you really run it? Sure you can, but it'll fail:
SQL> delete fromtest where rowid in (select rowid from table_name fetch first
2 Row_count rows only)
3 /
delete fromtest where rowid in (select rowid from table_name fetch first
*
ERROR at line 1:
ORA-00942: table or view does not exist
SQL>
Let's fix it. It is a good habit to precede parameters' names with a prefix so that you'd easily recognize them in the code; it also helps in where clause because - if you name the parameter the same as column, you'll get wrong result.
Also
, if you're worried about SQL injection, you could include call(s) to the `DBMS_ASSERT` package:
SQL> CREATE OR REPLACE PROCEDURE delete_rows
2 (par_table_name IN USER_TABLES.table_name%type,
3 par_row_count in number)
4 IS
5 l_str varchar2(200);
6 l_table_name user_tables.table_name%type;
7 BEGIN
8 l_table_name := dbms_assert.sql_object_name(par_table_name);
9
10 l_str := 'delete from ' || l_table_name ||' where rowid in ' ||
11 '(select rowid from ' || l_table_name ||
12 ' fetch first ' || par_row_count || ' rows only)';
13 dbms_output.put_line(l_str);
14 -- execute immediate l_str;
15 dbms_output.put_line(sql%rowcount);
16 END;
17 /
Procedure created.
OK; what's the new result:
SQL> exec delete_rows('test', 2);
delete from test where rowid in (select rowid from test fetch first 2 rows only)
PL/SQL procedure successfully completed.
Does this work? Yes, it does:
SQL> delete from test where rowid in (select rowid from test fetch first 2 rows only);
2 rows deleted.
SQL> rollback;
Rollback complete.
SQL>
OK; the final fix of the procedure: include execute immediate:
SQL> CREATE OR REPLACE PROCEDURE delete_rows
2 (par_table_name IN USER_TABLES.table_name%type,
3 par_row_count in number)
4 IS
5 l_str varchar2(200);
6 l_table_name user_tables.table_name%type;
7 BEGIN
8 l_table_name := dbms_assert.sql_object_name(par_table_name);
9
10 l_str := 'delete from ' || l_table_name ||' where rowid in ' ||
11 '(select rowid from ' || l_table_name ||
12 ' fetch first ' || par_row_count || ' rows only)';
13 -- dbms_output.put_line(l_str);
14 execute immediate l_str;
15 dbms_output.put_line('Deleted ' || sql%rowcount || ' row(s)');
16 END;
17 /
Procedure created.
SQL> exec delete_rows('test', 2);
Deleted 2 row(s)
PL/SQL procedure successfully completed.
SQL>
There are 2 mistakes.
You are missing a space after from.
row_count must be passed as parameter.
create or replace procedure delete_rows (table_name IN USER_TABLES.table_name%type, row_count in number)
IS
BEGIN
execute immediate 'delete from '||table_name||' where rowid in (select rowid from ' ||table_name||' fetch first '|| Row_count || ' rows only)';
dbms_output.put_line(sql%rowcount);
END;
/

SQL to Search for a particular VALUE in all COLUMNS of all TABLES in an entire SCHEMA in Oracle DB [duplicate]

This question already has answers here:
Search All Fields In All Tables For A Specific Value (Oracle)
(17 answers)
Closed 8 months ago.
Is there SQL to Search for a particular VALUE in all COLUMNS of all TABLES in an entire SCHEMA in Oracle DB. Please explain.
You'll need dynamic SQL, as you have to compose select statement.
Here's an example; adjust it according to your needs because datatypes matter (e.g. you can't compare numbers to dates and such; I'm handling it simply by skipping over errors):
SQL> declare
2 l_search_value varchar2(20) := '10';
3 l_str varchar2(500);
4 l_cnt number;
5 begin
6 for cur_r in (select table_name, column_name, data_type
7 from user_tab_columns
8 )
9 loop
10 begin
11 l_str := 'select count(*) from ' || cur_r.table_name ||
12 ' where ' || cur_r.column_name || ' = ' || l_search_value;
13 execute immediate l_str into l_cnt;
14
15 if l_cnt > 0 then
16 dbms_output.put_line(rpad(cur_r.table_name ||'.'||cur_r.column_name, 30, ' ') ||
17 ' found ' || l_cnt || ' time(s)');
18 end if;
19
20 exception
21 when others then
22 --dbms_output.put_line(rpad(cur_r.table_name ||'.'||cur_r.column_name, 30, ' ')
23 -- ||' - ' || cur_r.data_type ||'; '|| sqlerrm);
24 null;
25 end;
26 end loop;
27 end;
28 /
DEPARTMENTS.DEPARTMENT_ID found 1 time(s)
DEPT.DEPTNO found 1 time(s)
EMP.DEPTNO found 3 time(s)
EMPLOYEES.DEPARTMENT_ID found 3 time(s)
PL/SQL procedure successfully completed.
SQL>

Filter column value while using ALL_TAB_COLUMNS

In SQL Oracle, is there a way to filter an ALL_TAB_COLUMNS SELECT statement, by the values in a specific column?
Yes; you'll need PL/SQL with dynamic SQL to do that.
Here's an example I use to search through current user's tables, check the ones that contain ENAME column which contains SCOTT string within. The result says that two tables (EMPLOYEE and EMP) contain one row with such a value.
Adjust it to your needs.
SQL> SET SERVEROUTPUT ON
SQL> DECLARE
2 l_str VARCHAR2(500);
3 l_cnt NUMBER := 0;
4 BEGIN
5 FOR cur_r IN (SELECT u.table_name, u.column_name
6 FROM user_tab_columns u, user_tables t
7 WHERE u.table_name = t.table_name
8 AND u.column_name = 'ENAME'
9 )
10 LOOP
11 l_str := 'SELECT COUNT(*) FROM ' || cur_r.table_name ||
12 ' WHERE ' || cur_r.column_name || ' like (''%SCOTT%'')';
13
14 EXECUTE IMMEDIATE (l_str) INTO l_cnt;
15
16 IF l_cnt > 0 THEN
17 dbms_output.put_line(l_cnt ||' : ' || cur_r.table_name);
18 END IF;
19 END LOOP;
20 END;
21 /
1 : EMPLOYEE
1 : EMP
PL/SQL procedure successfully completed.
SQL>

How to check if all the tables in database are modified after an Update activity is performed on columns of tables?

I have to update all the tables having column name like '%DIV%' with a value DD wherever it is MG , I have written the script for it , but I am not getting the idea of how to verify if columns of all the tables are updated to value DD after the activity is performed. I have written this query .
SELECT 'SELECT '||OWNER||'.'||TABLE_NAME||', '||COLUMN_NAME||' FROM '||OWNER||'.'||TABLE_NAME||' WHERE '||COLUMN_NAME||' = ''MG'' ;'
FROM RADHA.CHANGE_TABLE
WHERE VALID_FLAG='Y'
I was planning to make a table structure like
OWNER TABLE_NAME PREV_COUNT
The PREV_COUNT will hold the count of rows having Column Value as MG and after the activity is performed , I will verify with following query if the corresponding rows have been updated to DD .
SELECT 'SELECT '||OWNER||'.'||TABLE_NAME||', '||COLUMN_NAME||' FROM '||OWNER||'.'||TABLE_NAME||' WHERE '||COLUMN_NAME||' = ''DD'' ;' FROM RADHA.CHANGE_TABLE WHERE VALID_FLAG='Y'
And the output of this query would go into table
OWNER TABLE_NAME NEW_COUNT
But I am not able to get how to fetch records from the Select query as it is the string which is written inside the select query but I want the result set such that I can insert the records in my table mentioned above, please guide how to approach further
I don't have your tables, but - based on Scott's sample schema, here's a script which search through all its tables for a column named JOB (line #8) and checks how many of them have value that looks like (hint: like) CLERK in it (line #12).
See how it works, adjust it so that it works for you.
SQL> DECLARE
2 l_str VARCHAR2(500);
3 l_cnt NUMBER := 0;
4 BEGIN
5 FOR cur_r IN (SELECT u.table_name, u.column_name
6 FROM user_tab_columns u, user_tables t
7 WHERE u.table_name = t.table_name
8 AND u.column_name = 'JOB'
9 )
10 LOOP
11 l_str := 'SELECT COUNT(*) FROM ' || cur_r.table_name ||
12 ' WHERE ' || cur_r.column_name || ' like (''%CLERK%'')';
13
14 EXECUTE IMMEDIATE (l_str) INTO l_cnt;
15
16 IF l_cnt > 0 THEN
17 dbms_output.put_line(l_cnt ||' : ' || cur_r.table_name);
18 END IF;
19 END LOOP;
20 END;
21 /
4 : EMP --> there are 4 CLERKs in the EMP table
PL/SQL procedure successfully completed.
SQL>

Dynamic sql/query: apostrophe in SELECT

So I have the problem, that there is a variable, which could contains different column names
and then in the SELECT I want to compare the column with a specific word.
But then it seems like the apostrophe make problems:
query := 'SELECT value FROM table WHERE ' || variable || ' like ''word''';
EXECUTE IMMEDIATE query INTO rec;
EXCEPTION WHEN OTHERS THEN htp.p(dbms_utility.format_error_stack);
SQL> set serveroutput on;
SQL> DECLARE
2 VAR VARCHAR2(20);
3 REC NUMBER;
4 query VARCHAR2(1000);
5 BEGIN
6 var := 'TABLE_NAME';
7 QUERY := 'SELECT count(*) FROM USER_TABLES WHERE ' || VAR || ' like ''%EMP%''';
8 dbms_output.put_line(query);
9 EXECUTE IMMEDIATE QUERY INTO REC;
10 dbms_output.put_line(rec);
11 END;
12 /
SELECT count(*) FROM USER_TABLES WHERE TABLE_NAME like '%EMP%'
1
PL/SQL procedure successfully completed.
With REC as collection type :
SQL> DECLARE
2 var VARCHAR2(20);
3 TYPE rec_typ
4 IS TABLE OF user_tables%ROWTYPE;
5 rec REC_TYP;
6 query VARCHAR2(1000);
7 BEGIN
8 var := 'TABLE_NAME';
9
10 query := 'SELECT * FROM USER_TABLES WHERE '
11 || var
12 || ' like ''%EMP%''';
13
14 dbms_output.Put_line(query);
15
16 EXECUTE IMMEDIATE query bulk collect INTO rec;
17
18 FOR i IN 1..rec.count LOOP
19 dbms_output.Put_line(Rec(i).table_name);
20 END LOOP;
21 END;
22 /
SELECT * FROM USER_TABLES WHERE TABLE_NAME like '%EMP%'
EMP
PL/SQL procedure successfully completed.
If you're searching for values in column that are equal to word then change like to =.
If you're searching for values in column that contains word then change like ''word'' to like ''%word%'' (don't forget about the third apostrophe that's closing dynamic query).