Closed. This question does not meet Stack Overflow guidelines. It is not currently accepting answers.
This question appears to be off-topic because it lacks sufficient information to diagnose the problem. Describe your problem in more detail or include a minimal example in the question itself.
Closed 8 years ago.
Improve this question
I need to extract last day of a specific week of the year. For example the last day of the 51st week of 2013.
I need a PL/SQL Procedure/Function which can do that.
Assuming LAST DAY in a week is 'SUNDAY'
A PL/SQL Function!
CREATE OR REPLACE FUNCTION GET_LAST_DATE_IN_WEEK( p_WEEK INTEGER, p_YEAR INTEGER)
RETURN DATE
IS
v_DATE DATE := NULL;
BEGIN
IF(p_WEEK IS NULL OR p_YEAR IS NULL) THEN
-- Handle the data validation here
v_DATE := NULL;
RETURN v_DATE;
END IF;
v_DATE := next_day(TRUNC(to_date(p_YEAR,'YYYY'),'YYYY')+(p_WEEK-1)*7,'SUNDAY');
IF TO_CHAR(v_DATE,'YYYY') > p_YEAR THEN
v_DATE := LAST_DAY(to_date('12'||p_YEAR,'MMYYYY'));
END IF;
RETURN v_DATE;
EXCEPTION WHEN OTHERS THEN
DBMS_OUTPUT.PUT_LINE('Error in GET_LAST_DATE_IN_WEEK : '||SQLERRM);
RETURN NULL;
END GET_LAST_DATE_IN_WEEK;
/
You invoke it this way!
SELECT GET_LAST_DATE_IN_WEEK(51,2013) FROM DUAL;
Good Luck!
This should be possible with dbms_scheduler:
declare
result_ date;
begin
dbms_scheduler.evaluate_calendar_string (
calendar_string => 'FREQ=YEARLY; BYWEEKNO=51; BYDAY=sun',
start_date => date '2013-01-01',
return_date_after => date '2013-01-01',
next_run_date => result_);
dbms_output.put_line(' Sunday of 51st week in 2013: ' || result_);
end;
/
Related
Closed. This question is not reproducible or was caused by typos. It is not currently accepting answers.
This question was caused by a typo or a problem that can no longer be reproduced. While similar questions may be on-topic here, this one was resolved in a way less likely to help future readers.
Closed 2 years ago.
Improve this question
I have a compilation error in my PL/SQL code, The audit_client table will be updated if any update or delete occurs on client_master
create or replace trigger t1
after update or delete on client_master
for each row
DECLARE
v1 varchar2(10);
v2 varchar2(80);
v3 number(11);
oper varchar2(15);
BEGIN
v1:= :old.CLIENT_NO
v2:= :old.NAME
v3:= :old.BALANCE
if updating then
oper:='update'
insert into audit_client values(v1,v2,v3,oper,v4,v5);
end if;
if deleting then
oper:='delete'
insert into audit_client values(v1,v2,v3,oper,v4,v5);
end if;
end;
/
Why would you declare those v variables at all? Somewhat simplified:
create or replace trigger t1
after update or delete on client_master
for each row
declare
l_oper varchar2(15);
begin
if updating then
l_oper := 'update';
elsif deleting then
l_oper := 'delete';
end if;
insert into audit_client
(client_no, name, balance, oper, col4, col5)
values
(:old.client_no, :old.name, :old.balance, l_oper, null, null);
end;
/
Instead of v4 and v5 I inserted NULL as you never said what should be put in there.
Also, as a good practice, you should always specify column list you're working with. That's why I made up those column names as I don't know their real names, but you do and you should use them.
Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 5 years ago.
Improve this question
Hey Im Looking at this Triggers for hours now can someone help me ?
These Triggers Are for a Database appenrently . I made sure all those tables exist.S
create or replace TRIGGER postleizahl_check
BEFORE
INSERT or UPDATE on Kunden
FOR EACH ROW
BEGIN
DECLARE PLZ varchar(5) ;
SET PLZ := (Select PLZ from PLZVERZEICHNIS where Ort = new.Ort) ;
if :new.Postleitzahl = PLZ then
INSERT INTO Kunden (KUNDEN_NUMMER,NACHNAME, VORNAME, STRAßE , POSTLEITZAHL, HAUSNUMMER,ORT )
VALUES (new.KUNDEN_NUMMER,new.NACHNAME,new.VORNAME, new.STRAßE ,new.POSTLEITZAHL, new.HAUSNUMMER,new.ORT );
else
RAISE_APPLICATION_ERROR
(-20001, 'PLZ Exestiert nicht. ');
end if ;
end;
CREATE OR REPLACE TRIGGER nachbestellen
AFTER INSERT ON Bestellungen
For Each Row
BEGIN
if Bestellungen.Datum = GETDATE THEN
INSERT INTO LIEFERANTENBESTELLUNG(Artikel_Nummer,LIEFERANTEN_NUMMER,DATUM,Artikel_Name)
VALUES(new.Artikel_Nummer,new.Artikel_Namen,new.DATUM,new.LIEFERANTEN_NUMMER);
END IF ;
END;
Your declare statement must come before your begin, and 'set' is a SQL*Server construct, not Oracle. All of your 'new' should be prefixed with a colon (:);
Additional comment: varchar is a valid type, but in Oracle you should be using varchar2. Currently they work the same way in Oracle, but Oracle reserves the right to change it in the future, most likely to conform to the ANSI standard for varchar.
CREATE OR REPLACE TRIGGER postleizahl_check
BEFORE INSERT OR UPDATE
ON kunden
FOR EACH ROW
DECLARE
plz VARCHAR (5);
BEGIN
plz := (SELECT plz
FROM plzverzeichnis
WHERE ort = :new.ort);
IF :new.postleitzahl = plz
THEN
INSERT INTO kunden (
kunden_nummer, nachname, vorname
, straße, postleitzahl, hausnummer
, ort
)
VALUES (
:new.kunden_nummer, :new.nachname, :new.vorname
, :new.straße, :new.postleitzahl, :new.hausnummer
, :new.ort
);
ELSE
raise_application_error (-20001, 'PLZ Exestiert nicht. ');
END IF;
END;
CREATE OR REPLACE TRIGGER nachbestellen
AFTER INSERT
ON bestellungen
FOR EACH ROW
BEGIN
IF bestellungen.datum = getdate
THEN
INSERT INTO lieferantenbestellung (
artikel_nummer, lieferanten_nummer, datum
, artikel_name
)
VALUES (
:new.artikel_nummer, :new.artikel_namen, :new.datum
, :new.lieferanten_nummer
);
END IF;
END;
Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 6 years ago.
Improve this question
I'm looking for a way to return one case-insensitive varchar2 from a table given as a parameter.
The database is configured to have as the first column the one I'll look into.
This is what I got to:
create or replace function generic_return(nam varchar2, table_n varchar2)
return varchar2
as
case_insensitive varchar2(300);
case_ins varchar2(300);
colu varchar2(30);
t_nam varchar2(30):=upper(table_n);
cursor point is execute inmediate select colu from t_nam;
cursor col is select column_name from cols where table_name=t_nam;
non_existent_table exception;
begin
case_ins:=upper(rtrim(ltrim(nam)));
open col;
fetch col into colu;
close col;
select column_name from cols where table_name=upper(table_n);
if colu is null then
raise non_existent_table;
end if;
open point;
loop
fetch point into case_insensitive;
exit when point%notfound;
if upper(case_insensitive)=case_ins then
return case_insensitive;
end if;
end loop;
close point;
return null;
end;
/
The function receives what to look for, and the name of the table to look into, then the first variables are to compare them, t_nam is to use the uppercased version of the second parameter... and from that there's the huge mess: I get the column name from the table in col, from cols, and then I try to make a cursor that goes around checking if what the tuple, going by the same modifications, is the first parameter, or not, if it happens to be, then it should return the unmodified version of the one in the table. Otherwise, it should return "null", which I'll treat differently on each procedure that uses it.
By null I mean nothingness, not the string.
Yes, you are right. That's a pretty huge mess. :-)
For starters, you cannot declare an explicit cursor as an execute immediate statement.
Next, if you want the first column in the table, you need to specify
WHERE column_id = 1
and then you can just grab it via a SELECT-INTO, no need for an explicit cursor.
Then you could try something like:
my_cur SYS_REFCURSOR;
BEGIN
...
OPEN my_cur FOR 'SELECT ' || first_col || ' FROM ' || t_name;
LOOP
FETCH my_cur INTO case_insensitive;
EXIT WHEN my_cur%NOTFOUND;
... logic for match ....
END LOOP;
CLOSE my_cur;
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
Closed. This question does not meet Stack Overflow guidelines. It is not currently accepting answers.
This question does not appear to be about programming within the scope defined in the help center.
Closed 9 years ago.
Improve this question
Is the usage of CASE wrong in the code below?
I am getting an error:
"PLS-00103: Encountered the symbol ";" when expecting one of the
following:
case The symbol "case" was substituted for ";" to continue. "
Code is :
create or replace PROCEDURE MIK_3PL_ITEM_ERRORS_PROC_1 IS
i_error_code varchar2(5);
i_desc varchar2(200);
CURSOR c_3pl_error IS
SELECT mie.client_item_id, mie.message_id,
mie.error_desc, mis.process_flag
FROM mik_3pl_item_error_etl mie,
dummy_staging mis
WHERE mie.client_item_id = mis.client_item_id
AND mie.message_id = mis.message_id;
BEGIN
dbms_output.put_line ('hello');
for i in c_3pl_error
loop
dbms_output.put_line ('in loop');
DECLARE
-- L_relations_exist VARCHAR2(1);
L_error_message VARCHAR2(255) := NULL;
L_return BOOLEAN := FALSE;
BEGIN
select error_code
into i_error_code
from mik_3pl_error_desc
where description = i.error_desc;
-- dbms_output.put_line(i_error_code);
CASE i_error_code
WHEN 'E2' THEN dbms_output.put_line ('in case');
END; -- end of CASE */
END; /*End of begin */
end loop;
END MIK_3PL_ITEM_ERRORS_PROC_1;
It needs to be:
...
CASE i_error_code
WHEN 'E2' THEN dbms_output.put_line ('in case');
END CASE; -- end of CASE */
END;
It's trying to treat the END; as the end of the block - matching that END with the BEGIN - and it knows the case is still open.
The documentation for the CASE statement shows that. (Not to be confused with a CASE expression, which does just have END. Ahem. Thank you Nicholas!)