How to make rename indexes re-runnable? - oracle

The scenario goes like this.
I created a partitioned table A with two indexes. Then inserted records from original table B which also has two indexes. Table B has 133 million rows.
Now I would like to rename old table B as '_old' including its indexes,
Finally, rename new partitioned table back to original table including its indexes.
I know i can simply write Alter statements to do the above tasks but the idea is to make it re-runnable! How can I do that?
DECLARE
PROCEDURE check_indexes
(
table_owner_in IN VARCHAR2
,table_name_in IN VARCHAR2
,index_name_in IN VARCHAR2
,new_index_name_in VARCHAR2
) IS
count_indexes NUMBER;
BEGIN
SELECT COUNT(*)
INTO count_indexes
FROM user_indexes
WHERE table_owner = table_owner_in
AND table_name = table_name_in
AND index_name = index_name_in;
IF count_indexes > 0
THEN
dbms_output.put_line('ALTER INDEX ' || index_name_in ||
' RENAME TO ' || new_index_name_in);
END IF;
END;
BEGIN
check_indexes(table_owner_in => 'UTILS_OWNER'
,table_name_in => 'OP_LOG_OLD'
,index_name_in => 'OL_MODULE_NAME_I'
,new_index_name_in => 'OL_MODULE_NAME_I_OLD');
check_indexes(table_owner_in => 'UTILS_OWNER'
,table_name_in => 'OP_LOG_OLD'
,index_name_in => 'OL_PK'
,new_index_name_in => 'OL_PK_OLD');
check_indexes(table_owner_in => 'UTILS_OWNER'
,table_name_in => 'OP_LOG'
,index_name_in => 'OL_MODULE_NAME_I_NEW'
,new_index_name_in => 'OL_MODULE_NAME_I');
check_indexes(table_owner_in => 'UTILS_OWNER'
,table_name_in => 'OP_LOG'
,index_name_in => 'OL_PK_NEW'
,new_index_name_in => 'OL_PK');
END;

Related

how to create a export table job in oracle 12c

I want to create a export table job, but I can't understand why its not working.
my table is Department
create table department (id number, name varchar2(200));
I want to export a csv file for per day at 9:00 pm. I need to create it.
I only know:
0. create a directory
create a PROCEDURE
create a DBMS_SCHEDULER.CREATE_PROGRAM
create a DBMS_SCHEDULER.CREATE_SCHEDULE
create a DBMS_SCHEDULER.CREATE_JOB
excute the job
thanks
Yes, you can use DBMS_SCHEDULER by creating in such a way
DECLARE
v_job_name VARCHAR2(32) := 'jb_exp_emp_data';
BEGIN
DBMS_SCHEDULER.CREATE_JOB(job_name => v_job_name,
job_type => 'STORED_PROCEDURE',
job_action => 'exp_emp_data',
start_date => TO_DATE('11-12-2021 21:00:10',
'DD-MM-YYYY HH24:MI:SS'),
repeat_interval => 'FREQ=DAILY; BYHOUR=21;',
auto_drop => false,
comments => 'Exports the content of the department table every day at 9:00PM o''clock ');
DBMS_SCHEDULER.ENABLE(v_job_name);
END;
/
that starts at the time defined by the start_date parameter, then repeats on every upcoming days at 9pm in the future.
I followed the steps below and it was successful ...
Create a directory (path of export file):
CREATE OR REPLACE DIRECTORY CSVDIR AS 'D:\';
Create a procedure:
Create Or Replace Procedure exp_emp_data Is
today varchar2(200);
fileName varchar2(200);
n_file utl_file.file_type;
v_string Varchar2(4000);
Cursor c_emp Is
Select
id, name
From
department;
Begin
select to_char(sysdate,'yyyymmdd','nls_calendar=persian') into today from dual;
fileName := 'empdata' || today || '.csv';
n_file := utl_file.fopen('CSVDIR', fileName, 'w', 4000);
v_string := 'ID, Name';
utl_file.put_line(n_file, v_string);
-- open the cursor and concatenate fields using comma
For cur In c_emp Loop
v_string := cur.id
|| ','
|| cur.name;
-- write each row
utl_file.put_line(n_file, v_string);
End Loop;
-- close the file
utl_file.fclose(n_file);
Exception
When Others Then
-- on error, close the file if open
If utl_file.is_open(n_file) Then
utl_file.fclose(n_file);
End If;
End;
/
-------- Test
Begin
exp_emp_data;
End;
/
Create a program:
BEGIN
DBMS_SCHEDULER.CREATE_PROGRAM (
program_name => 'PROG_EXPORT_TABLE',
program_action => 'exp_emp_data',
program_type => 'STORED_PROCEDURE');
END;
/
Create a job:
BEGIN
DBMS_SCHEDULER.CREATE_JOB (
job_name => 'JOB_EXPORT_TABLE',
job_type => 'STORED_PROCEDURE',
job_action => 'PROG_EXPORT_TABLE',
start_date => '16-nov-2021 11:50:00 pm',
repeat_interval => 'FREQ=DAILY;BYHOUR=23;BYMINUTE=59',
enabled => true
);
END;
/
And enabled it:
exec dbms_scheduler.enable('JOB_EXPORT_TABLE');

Create a Job in ORACLE

I have to create a job periodically.
But firstly I have create a simply job to learn how to create jobs in oracle, because is the first time I use a job.
It runs at systimestamp, but the job doesn't execute.
create or replace procedure job_test
is
begin
update table_a set value_user = 'JOB_EXECUTED' where id = 1;
commit;
end;
/
Then the scheduler job
begin
dbms_scheduler.create_job(
job_name => 'test_job_A',
job_type => 'stored_procedure',
job_action => 'job_test',
start_date = SYSTIMESTAMP,
enabled => true
);
end;
/
Then I consult the column value_user and it hasn't been updated.
select * from table_A where id = 1;
Can anyone explain me what I am missing.
create table user_count (
number_of_users NUMBER(4),
time_of_day TIMESTAMP
);
CREATE OR REPLACE PROCEDURE insert_user_count AS
v_user_count NUMBER(4);
BEGIN
SELECT count(*)
INTO v_user_count
FROM v$session
WHERE username IS NOT NULL;
INSERT INTO user_count
VALUES (v_user_count, systimestamp);
commit;
END insert_user_count;
BEGIN
DBMS_SCHEDULER.CREATE_PROGRAM (
program_name => 'PROG_INSERT_USER_COUNT',
program_action => 'INSERT_USER_COUNT',
program_type => 'STORED_PROCEDURE');
END;
BEGIN
DBMS_SCHEDULER.CREATE_SCHEDULE (
schedule_name => 'my_weekend_5min_schedule',
start_date => SYSTIMESTAMP,
repeat_interval => 'FREQ=MINUTELY; INTERVAL=5; BYDAY=SAT,SUN',
end_date => SYSTIMESTAMP + INTERVAL '30' day,
comments => 'Every 5 minutes');
END;
BEGIN
DBMS_SCHEDULER.CREATE_JOB (
job_name => 'my_user_count_job',
program_name => 'prog_insert_user_count',
schedule_name => 'my_weekend_5min_schedule');
END;
exec dbms_scheduler.enable('my_user_count_job’)
select * from user_count;
select job_name, status, run_duration, cpu_used
from USER_SCHEDULER_JOB_RUN_DETAILS
where job_name = ‘MY_USER_COUNT_JOB’;
Indeed your case should work but once(provided there already exists a row with id value equals to 1). Suppose you have an insert statement rather than an update, but doesn't repeat to populate the table with new incremented ID values.
For this, important point is to add repeat_interval argument such as below :
begin
dbms_scheduler.create_job(
job_name => 'test_job_A',
job_type => 'stored_procedure',
job_action => 'job_test',
start_date => SYSTIMESTAMP,
enabled => true,
repeat_interval => 'FREQ=MINUTELY;INTERVAL=5',
auto_drop => false,
comments => 'Inserts new records'
);
end;
/
which inserts new records for each five minutes.

PLSQL block for run the job using dbms_scheduler for gather statistics of 30 schema

I want to create one PL/SQL block where try to run the job using dbms_scheduler package and I want to gather schema stats of all 30 schema. Eg:
begin
dbms_scheduler_create_job(
job_name => ....,
job_type = > 'PL/SQL BLOCK',
job_action => 'declare
sch_lst dbms_stats.objecttab := dbms_stats.objecttab()
begin
sch_lst.extend(10);
sch_lst(1).ownname := "ab"; --ab is the Schema name
sch_lst(2).ownname := "cd";
.........
sch_lst(30).ownname := "xy";
dbms_stats.gather_schema_stats( ......)
end;
/
',
start_date => sysdate,
..........);
end;
/
Before start_date => sysdate, remove / and also in the schema name instead of " (double quote) use '' (double single quote) because it is inside the declare statement which is already inside single quote.
begin
dbms_scheduler_create_job(
job_name => ....,
job_type = > 'PL/SQL BLOCK',
job_action => 'declare
sch_lst dbms_stats.objecttab := dbms_stats.objecttab()
begin
sch_lst.extend(10);
sch_lst(1).ownname := ''ab''; --ab is the Schema name
sch_lst(2).ownname := ''cd'';
.........
sch_lst(10).ownname := ''kl'';
dbms_stats.gather_schema_stats( ......)
end;
',
start_date => sysdate,
..........);
end;
/
Then after compile this one. you can check the job by using execute dbms_schedule.run_job('<job_name>');
Firstly, you may create such a procedure :
create or replace procedure pr_schema_stats is
sch_lst owa.vc_arr;
begin
sch_lst(1) := 'ab';
sch_lst(2) := 'cd';
sch_lst(3) := 'ef';
sch_lst(4) := 'gh';
sch_lst(5) := 'ij';
sch_lst(6) := 'kl';
sch_lst(7) := 'mn';
sch_lst(8) := 'op';
sch_lst(9) := 'rs';
sch_lst(10):= 'tu';
for i in 1..10
loop
dbms_stats.gather_schema_stats(upper(sch_lst(i)),degree => 4, cascade => true );
end loop;
end;
and then call from scheduler as :
declare
v_job_name varchar2(70) := 'jb_gather_stats';
begin
dbms_scheduler.create_job(
job_name => v_job_name,
job_type => 'STORED_PROCEDURE',
job_action => 'pr_schema_stats',
start_date => to_date('04-12-2018 19:00:00', 'dd-mm-yyyy hh24:mi:ss'),
repeat_interval => 'FREQ=MONTHLY;INTERVAL=1;',
auto_drop => false,
comments => 'Produces statistics for Cost based SQL statements');
dbms_scheduler.enable(v_job_name);
end;
EDIT : You can replace your procedure's code with :
create or replace procedure pr_schema_stats is
begin
for c in (
select u.username,
row_number() over (order by u.username) as rn
from dba_users u
where u.account_status = 'OPEN'
and u.username not like 'SYS%'
)
loop
begin
dbms_stats.gather_schema_stats(c.username,degree => 4, cascade => true );
exception when others then
dbms_output.put_line(sqlerrm);
end;
end loop;
end;
to include all of the ordinary schemas in the analyze task.

merge report:ORA-28138:An invalid policy predicate was specified

When i excute a merge statement:
merge into employees e using new_employees n
on (e.employee_id = n.employee_id)
when matched then
update set e.salary = n.salary
when not matched then
insert (employee_id,first_name,last_name,email,phone_number,hire_date,
job_id,salary,commission_pct,manager_id,department_id)
values (n.employee_id,n.first_name,n.last_name,n.email,n.phone_number,
n.hire_date,n.job_id,n.salary,n.commission_pct,n.manager_id,
n.department_id);
it reports:ORA-28138:An invalid policy predicate was specified.
What's wrong with me?
I find this error is caused by Fine_Grained Auditing.I had created a policy before as below:
DBMS_FGA.add_policy (object_schema => 'primer',
object_name => 'employees',
policy_name => 'audit_policy',
audit_condition => 'employee_id = 100',
audit_column => 'phone_number,salary',
handler_schema => 'primer',
handler_module => 'FGA_SEND_MAIL(primer,employees,audit_policy)',
ENABLE => TRUE,
statement_types => 'select,insert,update,delete',
audit_trail => DBMS_FGA.db_extended,
audit_column_opts => DBMS_FGA.any_columns);
create or replace procedure primer.fga_send_mail (p_schema in varchar2,
p_obj in varchar2,
p_pol in varchar2)
as
begin
dbms_output.put_line ('Audit Trail Generated');
dbms_output.put_line ('SQL=' || sys_context ('USERENV', 'CURRENT_SQL'));
dbms_output.put_line ('USER' || sys_context ('USERENV', 'SESSION_USER'));
end;
What wrong with it?

Dynamicly Fill Array From Table at PL/SQL?

i need to pass array values dynamic at this PL/SQL CODE But the Array Just See The First Value the code : Hint( The code is big so i cut it at the issue part)please
if you need more information Kindly Ask me,Here is my try to pass it Dynamic.
Variable fill code:
FOR ET IN (SELECT EMAIL
FROM XX_INTERCO_SYS_CON
WHERE ACC_NO = Q.ACC_NO AND TYPE = 'TO')
LOOP
IF P_TO IS NOT NULL
THEN
P_TO := P_TO || ',''' || ET.EMAIL||'''';
ELSE
P_TO := ''''||ET.EMAIL||'''';
END IF;
END LOOP;
FOR EC IN (SELECT EMAIL
FROM XX_INTERCO_SYS_CON
WHERE ACC_NO = Q.ACC_NO AND TYPE = 'CC')
LOOP
IF P_CC IS NOT NULL
THEN
P_CC := P_CC || ',''' || EC.EMAIL||'''';
ELSE
P_CC := ''''||EC.EMAIL||'''';
END IF;
END LOOP;
The Array fill part :
XX_MAIL_PKG.SEND (P_FROM => P_FROM,
P_TO => XX_MAIL_PKG.ARRAY ( P_TO),
P_CC => XX_MAIL_PKG.ARRAY (P_CC),
P_SUBJECT => 'test',
P_HTML_MSG => P_HTML_OUTPUT,
P_SMTP_HOST => P_SMTP_HOST,
P_SMTP_PORT => P_SMTP_PORT,
P_TEXT_MSG => NULL,
X_ERR_MSG => X_ERR_MSG);
COMMIT;
DBMS_OUTPUT.PUT_LINE (X_ERR_MSG);
You appear to be using collections - so (without knowing what is in the XX_MAIL_PKG package) you could try this:
DECLARE
V_TO XX_MAIL_PKG.ARRAY;
V_CC XX_MAIL_PKG.ARRAY;
BEGIN
SELECT EMAIL
BULK COLLECT INTO V_TO
FROM XX_INTERCO_SYS_CON
WHERE ACC_NO = Q.ACC_NO AND TYPE = 'TO';
SELECT EMAIL
BULK COLLECT INTO V_CC
FROM XX_INTERCO_SYS_CON
WHERE ACC_NO = Q.ACC_NO AND TYPE = 'CC';
XX_MAIL_PKG.SEND (P_FROM => P_FROM,
P_TO => V_TO,
P_CC => V_CC,
P_SUBJECT => 'test',
P_HTML_MSG => P_HTML_OUTPUT,
P_SMTP_HOST => P_SMTP_HOST,
P_SMTP_PORT => P_SMTP_PORT,
P_TEXT_MSG => NULL,
X_ERR_MSG => X_ERR_MSG);
COMMIT;
DBMS_OUTPUT.PUT_LINE (X_ERR_MSG);
END;
/

Resources