I'm setting up a win auto job to accrue paid time off.
However, for personal time they only get a lump sum every year.
So I'm working on a pl/sql statement to check the date, but I can't get it to work.
I'm not sure what I'm doing wrong!!!
IF to_char(sysdate, 'MM/dd') = '01/01' THEN
PTO.personal_time := 8;
END IF;
update: to clarify. I want to check the date and if it is January first, to update the amount of personal time to 8 hours. I'm not getting any errors, but the amount of personal time isn't changing. There is no roll over and everyone gets one personal day, so i just set in on January 1st.
TABLE is a keyword and you cannot use it as a variable; however, if you replace table with the name of your variable then your code works perfectly (assuming that the variables of the appropriate names/types already exists):
DECLARE
-- declare a type which has a field names "field"
TYPE item_type IS RECORD(
field NUMBER
);
-- declare an "item" variable
item item_type;
BEGIN
-- start of your code
IF to_char(sysdate, 'MM/dd') = '04/25' THEN
item.field := 8;
END IF;
-- end of your code
DBMS_OUTPUT.PUT_LINE( item.field );
END;
/
which outputs:
8
db<>fiddle here
Related
how can the date be calculated depending on the input of a user?
That is, depending on what the user enters, 3 months will be added to the current date or 5, etc.
I tried to add a computation to the date pickers:
SUBMISSION_DATE displays only the current date (already implemented)
DATE_OF_ISSUE should be SUBMISSION_DATE +3months or +5months, depending on users input in another field.
I added as well a computation to this date with the following pl/sql function body, but it is not working.
DECLARE
sub_date DATE default null;
BEGIN
if :P75_THESISTYPE =1
then
sub_date := :P75_SUBMISSION_DATE +6;
else
sub_date := :P75_SUBMISSION_DATE +3;
END IF;
return sub_date;
end;
The page items are treated as VARCHAR2 so you need to convert them to dates before performing arithmetic on them:
DECLARE
sub_date DATE default null;
BEGIN
if :P75_THESISTYPE =1
then
sub_date := TO_DATE(:P75_SUBMISSION_DATE) +6;
else
sub_date := TO_DATE(:P75_SUBMISSION_DATE) +3;
END IF;
return sub_date;
end;
/
#TonyAndrews has the correct process, but as he followed your initial statement, it will not give the desired result. Adding an integer to a data add that number of days not months. What you need is the ADD_Months function; So:
DECLARE
sub_date DATE default null;
BEGIN
if :P75_THESISTYPE =1
then
sub_date := add_months(to_date(:P75_SUBMISSION_DATE),6);
else
sub_date := add_months(to_date(:P75_SUBMISSION_DATE),3);
end if
return sub_date;
end;
/
Of course the above assumes your variable's format matches your nls_data_format. Generally a dangerous assumption at best,
trying to create a procedure but i keep getting an error. here is the code
create or replace procedure HK.PURGE_LAN_DOTS
AS
batchsize number := 15000;
deleteline timestamp := current_timestamp - 365;
counter number := 0;
BEGIN
loop
DELETE FROM LAN.DOTS
WHERE rownum <= batchsize
AND TIMESTAMP < deleteline;
COMMIT;
counter:=counter + SQL%rowcount;
exit when batchsize > SQL%rowcount;
end loop;
HK.PURGE_LAN_DOTS;
END
this is the error iam getting
Error(36,12): PLS-00103: Encountered the symbol "." when expecting one of the following: ;
Probably just typos. This version ought to work (as long as HK has access to LAN.DOTS).
PL/SQL scripts are treated differently from standalone SQL in that they require both the trailing semicolon as well as a forward slash on a new line.
Slash vs. semicolon semantics in SQL*Plus is a bit odd; here's another question asked about precisely this:
When do I need to use a semicolon vs a slash in Oracle SQL?
Finally, you have included HK.PURGE_LAN_DOTS; before the END statement, when you probably intended to use END PURGE_LAN_DOTS;.
Note that you can't include the schema name in this closing tag, and the named closing tag is entirely optional (you can use just END;).
create or replace procedure HK.PURGE_LAN_DOTS
AS
batchsize number := 15000;
deleteline timestamp := current_timestamp - 365;
counter number := 0;
BEGIN
loop
DELETE FROM LAN.DOTS
WHERE rownum <= batchsize
AND TIMESTAMP < deleteline;
COMMIT;
counter:=counter + SQL%rowcount;
exit when batchsize > SQL%rowcount;
end loop;
END PURGE_LAN_DOTS;
/
The end of the code you posted has this:
end loop;
HK.PURGE_LAN_DOTS;
END
The END is missing a semicolon; but the previous line calls this procedure, which would cause infinite recursion (which Oracle would kill eventually).
I think you've corrupted this while posting and you actually have:
end loop;
END HK.PURGE_LAN_DOTS;
and now the error makes sense (although the report line and columns numbers don't quite).
Although the create statement takes an optional schema prefix:
create or replace procedure HK.PURGE_LAN_DOTS
the matching END does not. The overall statement can sort of be thought of as a mix of SQL and PL/SQL - not to the same extent that a trigger is, but here the effect is similar. The statement really does several things - it creates a procedure-type object called PURGE_LAN_DOTS under that schema, and compiles and stores the PL/SQL part of the code with the same name. The HK. bit is not part of the object name, and is not relevant to the PL/SQL engine - and the END is pure PL/SQL. If you look at the all_source view you'll see that the stored source will be PROCEDURE PURGE_LAN_DOTS AS ... without either the create or replace or the HK. prefix - the owner will be set to HK, though.
So, the END should only reference the PL/SQL object name, and cannot have a schema prefix:
create or replace procedure HK.PURGE_LAN_DOTS
...
end loop;
END PURGE_LAN_DOTS;
Not related, but:
deleteline timestamp := current_timestamp - 365;
will cause the current_timestamp value to be converted to a date to have 365 days subtracted, and that will then be converted back to a timestamp; which is more conversion than necessary, and loses the fractional seconds. You probably don't really care about that in this scenario, but sometimes it matters. To avoid both you could do either of these:
deleteline timestamp := current_timestamp - interval '365' day;
deleteline timestamp := current_timestamp - 365 * interval '1' day;
Once you switch to an interval you might be tempted to change that to current_timestamp - interval '1' year, but that will error with ORA-01839 if you run it on February 29th...
Also make sure you really do want current_timestamp and not systimestamp.
I have a table call OUTGOING which has many fields but the ones to be populated in this situation is:
FILENUMBER
OUTGOINGDATE
DEPARTMENT
now i have a report which whas an sql
SELECT APEX_ITEM.CHECKBOX2(1,registry.filenumber) "Select",
INCOMINGREQUESTNOTIFICATION.REQUESTEDFILE as REQUESTEDFILE,
INCOMINGREQUESTNOTIFICATION.FILENUMBER as FILENUMBER,
INCOMINGREQUESTNOTIFICATION.REQUESTEDDEPARTMENT as REQUESTEDDEPARTMENT,
INCOMINGREQUESTNOTIFICATION.REQUESTDATE as REQUESTDATE,
REGISTRY.STATUS as STATUS
from REGISTRY REGISTRY,
INCOMINGREQUESTNOTIFICATION INCOMINGREQUESTNOTIFICATION
where REGISTRY.FILENUMBER(+) =INCOMINGREQUESTNOTIFICATION .FILENUMBER
and INCOMINGREQUESTNOTIFICATION.STATUS ='PENDING'
which is fine .. what i need is for
INCOMINGREQUESTNOTIFICATION.FILENUMBER as FILENUMBER
INCOMINGREQUESTNOTIFICATION.REQUESTEDDEPARTMENT as REQUESTEDDEPARTMENT
and sysdate
to be inserted in the outgoing table under the relevant names of course.
I have a pl/sql
DECLARE
L_FILENUMBER WWV_FLOW_GLOBAL.VC_ARR2;
BEGIN
L_FILENUMBER := APEX_APPLICATION.G_F01;
FOR IDX IN 1 .. L_FILENUMBER.COUNT
LOOP
IF L_FILENUMBER(IDX) IS NOT NULL THEN
INSERT INTO OUTGOING
(FILENUMBER,OUTGOINGDATE,DEPARTMENT)
VALUES
((to_number(APEX_APPLICATION.G_F01(1)))
,SYSDATE
,to_char(APEX_APPLICATION.G_F02(2)) )
;
END IF;
END LOOP;
END;
which is not working.. However if i leave only filenumber
DECLARE
L_FILENUMBER WWV_FLOW_GLOBAL.VC_ARR2;
BEGIN
L_FILENUMBER := APEX_APPLICATION.G_F01;
FOR IDX IN 1 .. L_FILENUMBER.COUNT
LOOP
IF L_FILENUMBER(IDX) IS NOT NULL THEN
INSERT INTO OUTGOING
(FILENUMBER)
VALUES
((to_number(APEX_APPLICATION.G_F01(1)))
;
END IF;
END LOOP;
END;
its inserting only the file number fine . This is all being done via a submit button.
NB: i also tried putting outgoing date and department in the declare statement but it still doesnt work
I'd suggest you to learn how to use table aliases. SELECT you wrote is difficult to read due to VERY long table & column names; alias would certainly help.
As of your question: saying that "it is not working" doesn't help at all. What exactly doesn't work? Is there any error? If so, which one? Did you run the page in debug mode and check what's going on? If not, do that.
Apart from that, code you wrote doesn't make much sense - you're trying to insert the same values all over again. E.g. shouldn't APEX_APPLICATION.G_F01(1) be APEX_APPLICATION.G_F01(IDX)? Something like this:
begin
for idx in 1 .. apex_application.g_f01.count
loop
if apex_application.g_f01(idx) is not null then
insert into outgoing
(filenumber,
outgoingdate,
department
)
values
(apex_application.g_f01(idx),
sysdate,
apex_application.g_f02(idx)
);
end if;
end loop;
end;
Check (by inspecting the page) whether (tabular form?) items really are those that you've used (G_F01 and G_F02). If not, you'll have to fix that.
I didn't use any TO_NUMBER nor TO_CHAR functions; I don't know whether your really need them. Even if you don't have them, Oracle will perform implicit datatype conversion when possible, but it'll fail if you try to put e.g. 'abc123' into a NUMBER datatype column. You didn't share that information so - I left those out. Apply them if necessary.
Any help with this pl/sql and I would very much appreciate it. First off some basic info. I am using APEX 4.2 and have a Interactive report and form. I am interested in building a dynamic action on the form so that when the LEAVE_DATE is changed a PL/SQL function body (dynamic action) calculates whether the person has left within 12 month of their start date. Here are the columns in play and what I have attempted. The two calculations and be two separate dynamic actions. The first would be a calculation that results in a new date if the person left within 12 months of their BILL_READY DATE and the second returns 'Early Leaver' if within 12 months. Would be great if they could be in the same calculation though.
:P24_LEAVE_DATE (DATE)
:P24_BILL_READY (DATE)
:p24_NEW_LEAVE_DATE (DATE) CALULATED
:P24_MESSAGE (VARCHAR 255) --This would display 'Early Leaver' if within 12 months else null.
begin
case when :P24_LEAVING_DATE between :P24_BILL_READY AND (:P24_BILL_READY + 365) THEN (:P24_LEAVING_DATE - 30)
ELSE :P24_LEAVING_DATE
END CASE;
END;
Thanks for your help,
You need to create a dynamic action of type "change" on item P24_LEAVE_DATE. The action will be a set value action of type PLSQL function body. The code would be something along these lines:
declare
l_date date;
begin
if :p24_leaving_date between :p24_bill_ready and (:p24_bill_ready + 365)
then
l_date := :p24_leaving_date - 30;
else
l_date := :p24_leaving_date;
end if;
return l_date;
end;
The only thing I'm not sure off is how APEX handles date values. If they are handled as string values you need to add some string to date code in there.
I need to write a function that will give me a new due date for an invoice. This needs to be 12 working days after the current due date
Say the current due date is 01.Oct.2014. If I look at my calendar manually, I can see that the new date would be 17.Oct.2014 (need to exclude weekends).
However, I also have a table with Bank Holidays. This would have to be taken into consideration. So if I would have a Bank Holiday on 04.Oct.2014, the new due date should be 18.Oct.2014.
EDIT: My table with Bank Holidays would look something like this:
Year: Date: Description
2014 04.Oct.2014 Bank Holiday 1
Any help with this would be deeply appreciated, I'm stuck at this for almost a day now.
Thanks a lot in advance.
Kind regards
Gerben
Something like this should work:
DECLARE
l_date DATE := SYSDATE;
FUNCTION IS_WEEKEND(P_DATE IN DATE)
RETURN BOOLEAN
IS
l_daynum VARCHAR2(1) := to_char (P_DATE, 'D');
BEGIN
RETURN l_daynum = '6' OR l_daynum = '7';
END;
FUNCTION IS_HOLIDAY(P_DATE IN DATE)
RETURN BOOLEAN
IS
CURSOR c_exists IS
SELECT 1 FROM bank_holidays WHERE date = TRUNC(P_DATE)
;
l_count NUMBER;
BEGIN
OPEN c_exists;
l_count := c_exists%ROWCOUNT;
CLOSE c_exists;
RETURN l_count > 0;
END;
PROCEDURE ADD_WORKING_DAYS(P_DATE IN OUT DATE, P_DAYS IN NUMBER)
IS
l_workdays_added NUMBER := 0;
BEGIN
WHILE TRUE
LOOP
P_DATE := P_DATE + 1;
IF NOT IS_WEEKEND(P_DATE) AND NOT IS_HOLIDAY(P_DATE) THEN
l_workdays_added := l_workdays_added + 1;
END IF;
IF l_workdays_added = P_DAYS THEN
RETURN;
END IF;
END LOOP;
END;
BEGIN
ADD_WORKING_DAYS(l_date, 12);
END;
I ended up doing things slightly different. I have a table with all my bank holiday. I created a second table as a kind of calendar. In here, I loaded all dates in a year. I then flag it as weekend or bank holiday (2 separate columns).
I take my original due date, and add the 12 days. I then have a start and end date (v_due_date_old and v_due_date_new)
After that, I count how many days there are in my 'calendar' table, where either my flag for weekend or bank holiday is set to Yes. If v_due_date_new is on a Saturday, I add another day to my count.
I then add the new count to v_due_date_new.
As a last step, I check what day v_due_date_new is. If it is Saturday or Sunday, I add another 2 days