Reputation: 3
I want to make this code dynamic i.e in place of n_numb number := 1990 if i enter a different year it should execute based on that year you enter.
set SERVEROUTPUT ON
declare
v_test varchar2(80) := 'BORN';
n_numb number := 1990;
begin
while v_test <> 'Birthday'
loop
if n_numb = 1991 then v_test := 'Birthday';
end if;
dbms_output.put_line (v_test||': '||n_numb);
n_numb := n_numb + 1;
end loop;
v_test := 'Playschool';
while n_numb < 1994 AND v_test = 'Playschool' loop
dbms_output.put_line (v_test||': '||n_numb);
n_numb := n_numb + 1;
end loop;
v_test := 'Regularschool';
while n_numb < 2007 AND v_test = 'Regularschool' loop
dbms_output.put_line (v_test||': '||n_numb);
n_numb := n_numb + 1;
end loop;
v_test := 'Engineering';
while n_numb < 2011 AND v_test = 'Engineering' loop
dbms_output.put_line (v_test||': '||n_numb);
n_numb := n_numb + 1;
end loop;
v_test := 'SearchingJob';
while n_numb < 2013 AND v_test = 'SearchingJob' loop
dbms_output.put_line (v_test||': '||n_numb);
n_numb := n_numb + 1;
end loop;
v_test := 'Working';
while n_numb < 2014 AND v_test = 'Working' loop
dbms_output.put_line (v_test||': '||n_numb);
n_numb := n_numb + 1;
end loop;
end;
Upvotes: 0
Views: 116
Reputation: 2480
To make this code take a year input and print out based on the years elapsed, you will need to switch from changing the activity based on year-number to years-accumulated.
I'll add a couple examples below.
The first will modify your original code to allow switching n_numb
.
The second will refactor to use procedure
s to simplify things.
For a first example, I'll start with your original code, and add an accumulator
V_YEAR_ACCUMULATION
to measure the years. Then changing n_numb
to different values will get a different output.
DECLARE
V_TEST VARCHAR2(80) := 'BORN';
N_NUMB NUMBER := 1990;
V_YEAR_ACCUMULATION NUMBER := 0;
BEGIN
WHILE V_TEST <> 'Birthday'
LOOP
IF V_YEAR_ACCUMULATION = 1
THEN V_TEST := 'Birthday';
END IF;
DBMS_OUTPUT.put_line(V_TEST || ': ' || N_NUMB);
N_NUMB := N_NUMB + 1;
V_YEAR_ACCUMULATION := V_YEAR_ACCUMULATION + 1;
END LOOP;
V_TEST := 'Playschool';
WHILE V_YEAR_ACCUMULATION < 4 AND V_TEST = 'Playschool' LOOP
DBMS_OUTPUT.put_line(V_TEST || ': ' || N_NUMB);
N_NUMB := N_NUMB + 1;
V_YEAR_ACCUMULATION := V_YEAR_ACCUMULATION + 1;
END LOOP;
V_TEST := 'Regularschool';
WHILE V_YEAR_ACCUMULATION < 17 AND V_TEST = 'Regularschool' LOOP
DBMS_OUTPUT.put_line(V_TEST || ': ' || N_NUMB);
N_NUMB := N_NUMB + 1;
V_YEAR_ACCUMULATION := V_YEAR_ACCUMULATION + 1;
END LOOP;
V_TEST := 'Engineering';
WHILE V_YEAR_ACCUMULATION < 21 AND V_TEST = 'Engineering' LOOP
DBMS_OUTPUT.put_line(V_TEST || ': ' || N_NUMB);
N_NUMB := N_NUMB + 1;
V_YEAR_ACCUMULATION := V_YEAR_ACCUMULATION + 1;
END LOOP;
V_TEST := 'SearchingJob';
WHILE V_YEAR_ACCUMULATION < 23 AND V_TEST = 'SearchingJob' LOOP
DBMS_OUTPUT.put_line(V_TEST || ': ' || N_NUMB);
N_NUMB := N_NUMB + 1;
V_YEAR_ACCUMULATION := V_YEAR_ACCUMULATION + 1;
END LOOP;
V_TEST := 'Working';
WHILE V_YEAR_ACCUMULATION < 24 AND V_TEST = 'Working' LOOP
DBMS_OUTPUT.put_line(V_TEST || ': ' || N_NUMB);
N_NUMB := N_NUMB + 1;
V_YEAR_ACCUMULATION := V_YEAR_ACCUMULATION + 1;
END LOOP;
END;
/
And test it:
using n_numb := 1990
gives:
BORN: 1990
Birthday: 1991
Playschool: 1992
Playschool: 1993
Regularschool: 1994
...
...
SearchingJob: 2012
Working: 2013
but with n_numb := 1899
, you get:
BORN: 1899
Birthday: 1900
Playschool: 1901
Playschool: 1902
Regularschool: 1903
But, there is some refactoring that can simplify things.
In this second example, I'll create procedures to do the printing and move from one activity to the next as the years proceed. This will require less code.
First, create a procedure to print
the current activity
and progress the years
:
CREATE OR REPLACE PROCEDURE GROW_OLDER(P_ACTIVITY IN VARCHAR2, P_YEARS_TO_CONTINUE IN NUMBER, P_YEARS_ACCUMULATED IN OUT NUMBER)
IS
V_LOCAL_ACCUMULATION NUMBER := 0;
BEGIN
WHILE V_LOCAL_ACCUMULATION < P_YEARS_TO_CONTINUE LOOP
DBMS_OUTPUT.put_line(UTL_LMS.FORMAT_MESSAGE('%s: %s',P_ACTIVITY,TO_CHAR(P_YEARS_ACCUMULATED + V_LOCAL_ACCUMULATION)));
V_LOCAL_ACCUMULATION := V_LOCAL_ACCUMULATION + 1;
END LOOP;
P_YEARS_ACCUMULATED := P_YEARS_ACCUMULATED + P_YEARS_TO_CONTINUE;
END;
/
Then create a procedure to orchestrate the movement from activity to activity across the years:
CREATE OR REPLACE PROCEDURE MOVE_THROUGH_THE_YEARS(P_START_YEAR IN NUMBER)
IS
V_YEAR_ACCUMULATION NUMBER := P_START_YEAR;
BEGIN
GROW_OLDER('Born', 1, V_YEAR_ACCUMULATION);
GROW_OLDER('Birthday', 1, V_YEAR_ACCUMULATION);
GROW_OLDER('Playschool', 2, V_YEAR_ACCUMULATION);
GROW_OLDER('Regularschool', 13, V_YEAR_ACCUMULATION);
GROW_OLDER('Engineering', 4, V_YEAR_ACCUMULATION);
GROW_OLDER('SearchingJob', 2, V_YEAR_ACCUMULATION);
GROW_OLDER('Working', 1, V_YEAR_ACCUMULATION);
END;
/
Then Test it. Starting 1990
:
BEGIN
MOVE_THROUGH_THE_YEARS(1990);
END;
/
Born: 1990
Birthday: 1991
Playschool: 1992
Playschool: 1993
Regularschool: 1994
Regularschool: 1995
...
...
Engineering: 2010
SearchingJob: 2011
SearchingJob: 2012
Working: 2013
Or 2077
:
BEGIN
MOVE_THROUGH_THE_YEARS(2077);
END;
/
Born: 2077
Birthday: 2078
Playschool: 2079
Playschool: 2080
Regularschool: 2081
Regularschool: 2082
...
...
Engineering: 2097
SearchingJob: 2098
SearchingJob: 2099
Working: 2100
EDIT If you only want to print each activity once, you can replace the GROW_OLDER
procedure above with an alternative that does no looping.
CREATE OR REPLACE PROCEDURE GROW_OLDER(P_ACTIVITY IN VARCHAR2, P_YEARS_TO_CONTINUE IN NUMBER, P_YEARS_ACCUMULATED IN OUT NUMBER)
IS
BEGIN
DBMS_OUTPUT.put_line(UTL_LMS.FORMAT_MESSAGE('%s: %s',P_ACTIVITY,TO_CHAR(P_YEARS_ACCUMULATED)));
P_YEARS_ACCUMULATED := P_YEARS_ACCUMULATED + P_YEARS_TO_CONTINUE;
END;
/
CREATE OR REPLACE PROCEDURE MOVE_THROUGH_THE_YEARS(P_START_YEAR IN NUMBER)
IS
V_YEAR_ACCUMULATION NUMBER := P_START_YEAR;
BEGIN
GROW_OLDER('Born', 1, V_YEAR_ACCUMULATION);
GROW_OLDER('Birthday', 1, V_YEAR_ACCUMULATION);
GROW_OLDER('Playschool', 2, V_YEAR_ACCUMULATION);
GROW_OLDER('Regularschool', 13, V_YEAR_ACCUMULATION);
GROW_OLDER('Engineering', 4, V_YEAR_ACCUMULATION);
GROW_OLDER('SearchingJob', 2, V_YEAR_ACCUMULATION);
GROW_OLDER('Working', 1, V_YEAR_ACCUMULATION);
END;
/
Then test it:
BEGIN
MOVE_THROUGH_THE_YEARS(1990);
END;
/
Result:
Born: 1990
Birthday: 1991
Playschool: 1992
Regularschool: 1994
Engineering: 2007
SearchingJob: 2011
Working: 2013
Edit If you need an anonymous block with one row per activity, here's an example:
DECLARE
V_YEARS NUMBER := 1990;
BEGIN
DBMS_OUTPUT.put_line(UTL_LMS.FORMAT_MESSAGE('Born: '||TO_CHAR(V_YEARS)));
V_YEARS := V_YEARS + 1;
DBMS_OUTPUT.put_line(UTL_LMS.FORMAT_MESSAGE('Birthday: '||TO_CHAR(V_YEARS)));
V_YEARS := V_YEARS + 1;
DBMS_OUTPUT.put_line(UTL_LMS.FORMAT_MESSAGE('Playschool: '||TO_CHAR(V_YEARS)));
V_YEARS := V_YEARS + 2;
DBMS_OUTPUT.put_line(UTL_LMS.FORMAT_MESSAGE('Regularschool: '||TO_CHAR(V_YEARS)));
V_YEARS := V_YEARS + 13;
DBMS_OUTPUT.put_line(UTL_LMS.FORMAT_MESSAGE('Engineering: '||TO_CHAR(V_YEARS)));
V_YEARS := V_YEARS + 4;
DBMS_OUTPUT.put_line(UTL_LMS.FORMAT_MESSAGE('SearchingJob: '||TO_CHAR(V_YEARS)));
V_YEARS := V_YEARS + 2;
DBMS_OUTPUT.put_line(UTL_LMS.FORMAT_MESSAGE('Working: '||TO_CHAR(V_YEARS)));
V_YEARS := V_YEARS + 1;
END;
/
Output is same as all the other examples:
Born: 1990
Birthday: 1991
Playschool: 1992
Regularschool: 1994
Engineering: 2007
SearchingJob: 2011
Working: 2013
Upvotes: 1