How to update a parameter in a job in Oracle SQL - plsql

I have just created a job using SQL Developer build-in wizard and i would like to change the parameters of the created job from my application.
The job is launching a stored procedure every day at 7 o'clock.
In the application I have to field:
Disable: true/false
Hour: 10:00
And this is my job and fields I would like to update depending on what was selected in the app:
I see two ways of doing it:
Make the fields dependent on the values in the table
Make a pl/sql block that updates the values
Of course I don't know how to do it (in the first option the select statement doesn't work and in the second I don't know how to acces the jobs fields)
Please help

Begin
dbms_scheduler.disable( 'ATOS."job_email_notifications"' );
DBMS_SCHEDULER.SET_ATTRIBUTE ( name => 'ATOS."job_email_notifications"', attribute => 'repeat_interval', value => 'freq=daily;byday=FRI,SAT;byhour=20;byminute=0; bysecond=0');--change value--as per need
dbms_scheduler.enable( 'ATOS."job_email_notifications"' );
End;
/

Use below procedure for dynamic updates based on values
Create or replace procedure change_attributes(a_job_name varchar2, a_param varchar2, a_new_val varchar2)
As
Begin
dbms_scheduler.disable( a_job_name);
DBMS_SCHEDULER.SET_ATTRIBUTE ( name => a_job_name,attribute => a_param, value => a_new_val);
dbms_scheduler.enable( a_job_name);
End;
/

Related

How to pass bind variable as IN OUT parameter in PLSQL procedure

I want to use 1st parameter of my procedure EMP_ID as IN OUT parameter. Originally it's IN parameter and this procedure is working fine, but as the last line concern
htp.p('Inserted for Employee-id '||EMP_ID);
I want to use this line in anonymous block and most importantly it should be a bind variable because I am creating the REST API in which user will only enter values and it will be taken as bind variable in oracle Apex and the below procedure is working fine with respect of IN parameter.
create or replace procedure att_time_ins (EMP_ID in varchar2, ORG_ID in number,V_TIME_STATUS in number) is
BEGIN
INSERT INTO TIME_ATTENDANCE_POOL
(EMPLOYEE_ID, ATTENDANCE_DATE,TIME_HOURS,TIME_MINUTES,TIME_STATUS,LOCATION_ID,ORG_ID,PREPARED_ON )
VALUES
(EMP_ID, to_date(sysdate,'DD/MM/YYYY'),to_char(sysdate,'HH24') ,to_char(sysdate,'MI'),V_TIME_STATUS,null,ORG_ID,
to_date(sysdate,'DD/MM/YYYY') );
COMMIT;
time_management.create_attendance_sheet(v_org_id => ORG_ID,
v_employee_id => EMP_ID,
target_date => to_date(sysdate,'DD/MM/YYYY'));
htp.p('Inserted for Employee-id '||EMP_ID);
end att_time_ins;
I am calling my procedure in this way
begin
att_time_ins(:employee_id,:org_id,:time_status);
end;
Please help me to modify this stuff according to IN OUT Parameter i.e Employee_id should be IN OUT parameter. There is no proper documentation regarding passing bind variables as in out prameter in PLSQL Block.
Let us say you have a procedure named PR_PROC, you can use VARIABLE statement for passing IN OUT or OUT kind of variables.
CREATE OR REPLACE PROCEDURE PR_PROC (EMP_NAME IN VARCHAR2,
EMP_ID IN OUT VARCHAR2)
IS
BEGIN
DBMS_OUTPUT.PUT_LINE (EMP_NAME||EMP_ID);
END;
VARIABLE KURSOR VARCHAR2
BEGIN
:KURSOR:='4';
PR_PROC('SENIOR',:KURSOR);
END;
Note: If you are using TOAD Editor you can press F5 to make it work.
Oracle VARIABLE

PLSQL is it possible to update a table column on a certain date?

I have this table :
penalities(player,dateofpenality,penalityDays,status)
Based on certain criteria a player is added to this table where the status goes to 'yes'. I want his status to change to 'no' jusrt after the penality period (=penalityDays) is gone.
I thought of a trigger on date but I couldn't find it in plsql.
Please note that I don't want to delete the player as I need the history .
The only way to do this is to schedule a background job which kicks off once a day.
Write a simple stored procedure to apply the change of status:
create or replace procedure update_penalty_status as
begin
update penalties
set status = 'no'
where sysdate >= dateofpenality + penalityDays
and status = 'yes';
commit;
end update_penalty_status;
Then submit a job to run once a day. This uses DBMS_SCHEDULER (available since 10g) rather than the older DBMS_JOB.
BEGIN
DBMS_SCHEDULER.CREATE_JOB (
job_name => 'your_schema.my_job1',
job_type => 'PLSQL_BLOCK',
job_action => 'BEGIN update_penalty_status; END;',
start_date => trunc(sysdate)+1,
repeat_interval => 'FREQ=DAILY'
enabled => TRUE,
comments => 'Revoke expired penalties');
END;
/
Note that you will need the CREATE JOB privilege to do this. You may need to ask your DBA for help and guidance. Normally I would link to the Oracle documentation at this point, but I think the Oracle-Base article is a friendlier place to start.

Update statement works in normal mode, but not in procedure

I want to upload image from directory to database blob field. For those reason I write this code. Code alone works well but is not working as a procedure.
What is the problem ? I cannot understand. Here is the code:
DECLARE
dest_loc BLOB;
src_loc BFILE;
BEGIN
src_loc:= BFILENAME('ALL_IMG_DIR','SDFGASDF1544.jpg');
DBMS_LOB.FILEOPEN(src_loc);
DBMS_LOB.CREATETEMPORARY(dest_loc,true);
DBMS_LOB.LOADFROMFILE(dest_lob => dest_loc, src_lob => src_loc,amount=>dbms_lob.getlength(src_loc) );
UPDATE STUDENT
SET IMAGE=dest_loc
WHERE
REG_CODE = 'SDFGASDF1544';
DBMS_LOB.CLOSE(src_loc);
end;
But when I write this code as a procedure, like
CREATE OR REPLACE PROCEDURE img_to_blob_student(Vreg_code varchar2)
is
dest_loc BLOB;
src_loc BFILE;
BEGIN
src_loc := BFILENAME('ALL_IMG_DIR','SDFGASDF1544.jpg');
DBMS_LOB.FILEOPEN(src_loc);
DBMS_LOB.CREATETEMPORARY(dest_loc,true);
DBMS_LOB.LOADFROMFILE(
dest_lob => dest_loc,
src_lob => src_loc,
amount=>dbms_lob.getlength(src_loc)
);
UPDATE STUDENT
SET IMAGE=dest_loc
WHERE REG_CODE = 'SDFGASDF1544';
DBMS_LOB.CLOSE(src_loc);
end;
And call like
img_to_blob_student('123');
I get
ERROR IS: `ORA-00900: invalid SQL statement in procedure`
to call the procedure, did you use the execstatement?
exec img_to_blob_student('123');

Issue With PL/SQL Bind Variables

Recently, I deployed an Oracle WareHouse Builder (OWB) mapping. In the scenario I'm working right now, this mapping (ETL process) needs to be fired up by a trigger after an Update statement takes place on the fact table (working with WriteBack values).
As the mapping is deployed to the target schema as a package, the trigger must call the main procedure that OWB creates for the package. At first I didn't knew how to accomplish this task, but SQL Developer gave me a hint:
So, I took this code and put it inside my trigger. Like this:
CREATE OR REPLACE TRIGGER RESPALDO_HISTORIAL
AFTER UPDATE ON MONITOR_FT_TAB
FOR EACH ROW
DECLARE
P_STATUS VARCHAR2(200);
P_MAX_NO_OF_ERRORS VARCHAR2(200);
P_COMMIT_FREQUENCY VARCHAR2(200);
P_OPERATING_MODE VARCHAR2(200);
P_BULK_SIZE VARCHAR2(200);
P_AUDIT_LEVEL VARCHAR2(200);
P_PURGE_GROUP VARCHAR2(200);
P_JOB_AUDIT VARCHAR2(200);
BEGIN
P_MAX_NO_OF_ERRORS := NULL;
P_COMMIT_FREQUENCY := NULL;
P_OPERATING_MODE := NULL;
P_BULK_SIZE := NULL;
P_AUDIT_LEVEL := NULL;
P_PURGE_GROUP := NULL;
P_JOB_AUDIT := 'TRUE';
SINIESTROS_MARCADOS_MAP.MAIN(
P_STATUS => P_STATUS,
P_MAX_NO_OF_ERRORS => P_MAX_NO_OF_ERRORS,
P_COMMIT_FREQUENCY => P_COMMIT_FREQUENCY,
P_OPERATING_MODE => P_OPERATING_MODE,
P_BULK_SIZE => P_BULK_SIZE,
P_AUDIT_LEVEL => P_AUDIT_LEVEL,
P_PURGE_GROUP => P_PURGE_GROUP,
P_JOB_AUDIT => P_JOB_AUDIT
);
:P_STATUS := P_STATUS;
END RESPALDO_HISTORIAL;
/
When I tried to compile this trigger, I got this screen:
In this screen I tried clicking "Aplicar" (Apply in spanish) with and without the NULL checkbox, always getting this output:
TRIGGER RESPALDO_HISTORIAL compilado
Errors: check compiler log
Then I ran the SHOW ERRORS command and I got this:
33/3 PLS-00049: bad bind variable 'P_STATUS'
Now I don't quite understand these bind variables. If this is the code generated by SQL Developer to run the package, then why I get this error??
Please help! I need some guidelines in this matter!
Greetings!
A colon preceding a variable indicates that that variable is a bind variable. Bind variables of this type are typically used to pass values in and out of anonymous blocks. They're not allowed in procedures, functions, or triggers. In this case, you need to remove the line :P_STATUS := P_STATUS;.

How to dynamically add content to email in PL/SQL?

I'm using Oracle apex and am trying to practice with automatic emails. Ideally, this is how the scenario would go: A user can 'recommend' games to friends through his wishlist. The user selects the game(s) they would like to recommend though a checkbox, then selects the friends and email content. The code I have in place for this is as follows:
DECLARE
content VARCHAR2(4000) := :P4_EMAIL || 'Here are the game(s):';
game VARCHAR2(100);
i NUMBER := 1;
/*Declare the cursor and it's query */
cursor CURSOR IS
SELECT name
from gs_games
where game_id = APEX_APPLICATION.G_F01(i)
FOR UPDATE;
BEGIN
FOR i in 1..APEX_APPLICATION.G_F01.count
LOOP
OPEN cursor;
FETCH cursor INTO game;
CLOSE cursor;
END LOOP;
htmldb_mail.Send(p_to => :P4_FRIENDS,
p_from => 'gametracker#gametracker.com',
p_subj => 'Game recommendations from ' || :F56_USER_NAME,
p_body => content || ' ' || game);
END;
This only partially works. For a single selection, everyone works perfectly, but once the user selects multiple games, then the email only contains the name of the first game checked off, instead of every game as it should. I realize this is tied to the way I've got my cursor set up, but I'm not entirely sure how I can use it while keeping that for loop active. Does anyone have any ideas? Thank you.
The immediate problem is that every time you fetch the next row from the cursor into your local variable game, you are overwriting the prior value of that variable. Once you've fetched every row from the cursor, game will have the value of whatever the last row you processed was.
Assuming that you want your email to contain a comma-separated list of game names, you could do something like
-- You probably want to create this function inside of a package that provides other methods
-- for interacting with games
CREATE OR REPLACE FUNCTION get_game_name( p_game_id IN gs_games.game_id%type )
RETURN gs_games.name%type
IS
l_name gs_games.name%type;
BEGIN
SELECT name
INTO l_name
FROM gs_games
WHERE game_id = p_game_id;
RETURN l_name;
END get_game_name;
DECLARE
l_content VARCHAR2(4000) := :P4_EMAIL || 'Here are the game(s):';
l_game_list VARCHAR2(100);
BEGIN
FOR i in 1..APEX_APPLICATION.G_F01.count
LOOP
l_game_list := l_game_list || ', ' || get_game_name( APEX_APPLICATION.G_F01(i) );
END LOOP;
l_game_list := LTRIM( ', ' );
apex_mail.send( p_to => :P4_FRIENDS,
p_from => 'gametracker#gametracker.com',
p_subj => 'Game recommendations from ' || :F56_USER_NAME,
p_body => l_content || ' ' || l_game_list);
END;
A few notes about style
Naming a cursor CURSOR is problematic and should be avoided at all costs. If you do need to declare a cursor, you really ought to give it a meaningful name.
Local variables generally ought to be named in such a way that differentiates them from the names of columns in tables (in my case, I use a l_ prefix for local variables and a p_ prefix for parameters though there are many different valid conventions. This is important in PL/SQL because identifiers in SQL statements are resolved first using the names of columns in the table and then using local variables. That makes it far too easy to inadvertently write code that uses a column when you meant for it to use a local variable if you don't have some convention to make it clear which you're using.
You don't want to use a cursor to select a single row of data. If you have a query that you know should return exactly 1 row, use a SELECT INTO.
I created a separate function to get the name for a particular game_id because that maximizes reuse-- there will likely be many other places that you need to do something similar so you want to write that code once and use it many times. It would be perfectly legal to put the SELECT INTO into the loop in your anonymous PL/SQL block, it would be preferable to factor that code out into a function.
Assuming you are using a vaguely recent version of APEX, you should be using the apex_mail package not the old htmldb_mail package. There shouldn't be any functional difference between the two but HTML DB was the old name for Oracle APEX many releases ago so it's a good idea to phase out the use of the old package names.

Resources