How can I change this nested IF statement to a compound IF statements, I know it is pretty much the same but I do not know how to implement that with my code.
SET VERIFY OFF
DECLARE
v_idno donornew.idno%TYPE :=&input_idno;
v_yrgoal donornew.yrgoal%TYPE;
v_newgoal donornew.yrgoal%TYPE;
v_state donornew.state%TYPE;
v_city donornew.city%TYPE;
BEGIN
SELECT yrgoal, state, city INTO v_yrgoal, v_state, v_city
FROM donornew
WHERE idno = v_idno;
IF v_state = 'MA' AND ( v_yrgoal < 400 or v_city = 'Fall River') THEN
v_newgoal := v_yrgoal * 2.5;
ELSE
v_newgoal := v_yrgoal * 1.3;
END IF;
UPDATE donornew
SET yrgoal = v_newgoal
WHERE idno = v_idno;
COMMIT;
END;
/
SET VERIFY ON
Hello bascically for thsi purpose i will suggest you to go with purely SQL logic rather than PLSQL approach. Merge is the perfect example to resolve your issues.
-- Approach is to use SQL approach rather then using PLSQL approach.
MERGE INTO donornew D USING
(SELECT yrgoal,
state,
city,
idno,
CASE
WHEN state = 'MA'
AND (yrgoal < 400
OR city = 'Fall River')
THEN yrgoal * 2.5
ELSE yrgoal * 1.3
END newgoal
FROM donornew
WHERE idno = v_idno -- Input IDNO
)A ON (d.idno = a.idno )
WHEN MATCHED THEN
UPDATE SET yrgoal = a.newgoal;
Let me know if this helps.
Related
Im trying to create a procedure for a railway database on phpmyadmin. In which the train number, train date, and category is read from the passenger. On the basis of the values provided by the passenger, corresponding record is retrieved from the Train_Status table. If the desired category is AC, then total number of AC seats and number of booked AC seats are compared in order to find whether ticket can be booked or not. Similarly, it can be checked for the general category. If ticket can be booked, then passenger details are read and stored in the Passenger table.
I have scratched my head on the procdure syntax but it is still giving an error. Tried changing syntax, removing the check condtion from variables but nothing seems to work.
The error it gives is
"#1064 - You have an error in your SQL syntax; check the manual that
corresponds to your MariaDB server version for the right syntax to use
near 'CHECK (train_number>=1 AND train_number<=5); DECLARE t_date
DATE; DECLA...' at line 6"
The mariadb version is 10.4.25
Here it is what I created
DELIMITER $$
CREATE PROCEDURE Booking (t_num int(1), t_date DATE, category varchar(10) )
BEGIN
DECLARE t_num int(1) CHECK (train_number>=1 AND train_number<=5);
DECLARE t_date DATE;
DECLARE category ENUM('AC', 'General');
DECLARE status ENUM('Confirmed', 'Waiting');
DECLARE getTrain CURSOR FOR
SELECT * FROM Train_Status
WHERE train_number = t_num AND train_date = t_date;
DECLARE trec Train_Status % ROWTYPE;
DBMS_OUTPUT.PUT_LINE('READING VALUES');
t_num := &t_num;
t_date := '&t_date';
category := '&category';
OPEN getTrain;
LOOP
FETCH FROM getTrain INTO trec;
EXIT WHEN getTrain % NOTFOUND;
IF(category = 'AC') THEN
IF(trec.t_acseats - trec.b_acseats) > 0 THEN
status := 'Confirmed';
DBMS_OUTPUT.PUT_LINE('Seat Confirmed');
ELSIF(trec.t_acseats - trec.b_acseats) > -2 THEN
status := 'Waiting';
DBMS_OUTPUT.PUT_LINE('Seat Waiting');
ELSE
DBMS_OUTPUT.PUT_LINE('Seat Not Available');
EXIT;
END IF;
IF status = 'Confirmed' OR status = 'Waiting' THEN
UPDATE Train_Status SET b_acseats = b_acseats + 1 WHERE
TrainNumber = t_num and TrainDate = t_date;
END IF;
ELSIF(category = 'General') THEN
IF(trec.t_genseats - trec.b_genseats) > 0 THEN
status := 'Confirmed';
DBMS_OUTPUT.PUT_LINE('Seat Confirmed');
ELSIF(trec.t_genseats - trec.b_genseats) > -2 THEN
status := 'Waiting';
DBMS_OUTPUT.PUT_LINE('Seat Waiting');
ELSE
DBMS_OUTPUT.PUT_LINE('Seat Not Available');
EXIT;
END IF;
IF status = 'Confirmed' OR status = 'Waiting' THEN
UPDATE Train_Status SET b_genseats = b_genseats + 1
WHERE TrainNumber = t_num and TrainDate = t_date;
END IF;
ELSE
DBMS_OUTPUT.PUT_LINE('Invalid Category');
END IF;
IF status = 'Confirmed' OR status = 'Waiting' THEN
INSERT INTO Passengers
VALUES ('&T_ID', t_num, t_date, '&Name', &Age, '&Sex', '&Address', status, category);
END IF;
END LOOP;
CLOSE getTrain;
END $$
DELIMITER ;
Check can't be used while declaring the variables. Only name and data type should be there.
Check cursor syntax from MariaDB documentation.
These two things will solve your 70% problems. Rest you can figure out.
I am running the below PL/SQL block in SQL Developer. I am getting the error Bind Variable "prmMediaDate" is Not Declared. Someone please tell what is missing here:
set serveroutput on;
/* RUN the following as a SCRIPT (F5) */
DECLARE
VARIABLE prmMediaDate varchar2(10);
VARIABLE prmSchdDiv varchar2(2);
VARIABLE prmSchdStore varchar2(4);
VARIABLE prmSchdAssoc varchar2(8);
BEGIN
select '07/17/2017' into :prmMediaDate FROM DUAL;
select '91' into :prmSchdDiv FROM DUAL;
select '91916559' into :prmSchdAssoc FROM DUAL;
SELECT
NVL(ODIV,LA.LABORLEV1NM) AS "schd_division"
,NVL(OLOC,LA.LABORLEV4NM) AS "schd_location"
,NVL(OZONE,LA.LABORLEV5NM) AS "schd_dept"
,NVL(O.ORGPATHTXT,LA.LABORLEV1NM||'-'||LA.LABORLEV4NM||'-'||LA.LABORLEV5NM) AS "orgpath_of_shift"
,SA.SHIFTASSIGNID AS "shiftassignid"
,SA.SHIFTCODEID AS "shiftcodeid"
,SA.ENTEREDONDTM AS "assignmnt_add_dtm"
,ST.ENTEREDONDTM AS "assignmnt_edit_dtm"
,CASE WHEN ST.ACTIONTYPEID IS NULL THEN SA.ENTEREDONDTM ELSE ST.ENTEREDONDTM END as "last_action_dt"
,ST.ACTIONTYPEID AS "last_action_cd"
,AT.SHORTNM AS "last_action_descr"
,SA.DELETEDSW AS "deletedsw"
,TRUNC(SA.SHIFTSTARTDATE) AS "shift_start_date"
,TRUNC(SA.SHIFTENDDATE) AS "shift_end_date"
,TO_CHAR(SA.SHIFTSTARTDATE, 'HH24:MI:SS') AS "shift_start_time"
,TO_CHAR(SA.SHIFTENDDATE, 'HH24:MI:SS') AS "shift_end_time"
,CASE SA.SHIFTTYPEID WHEN 1 THEN 'WORK SHIFT' WHEN 2 THEN 'UNAVAIL' WHEN 3 THEN 'HIDE SHFT' WHEN 4 THEN 'SCHD PAYCD EDIT' WHEN 5 THEN 'HIDE WRK SHFT' WHEN 6 THEN 'HIDE UNAVAIL DAY' ELSE 'UNDEFINED' END as "segment"
,NVL(LA.LABORLEV2DSC,'9999') AS "sell_nonsell"
,P.PERSONNUM AS "assoc_nbr"
,SA.ENTEREDONDTM AS "entered_on_dtm"
from PERSON P
JOIN SHIFTASSIGNMNT SA on SA.EMPLOYEEID = P.PERSONID
JOIN COMBHOMEACCT HA on (P.PERSONID = HA.EMPLOYEEID)
LEFT JOIN SHFTSEGORGTRAN SSOT on SSOT.SHIFTASSIGNID = SA.SHIFTASSIGNID
LEFT JOIN ORGX O on O.ORGIDSID = SSOT.ORGIDSID
LEFT JOIN SHFTASGNMNTTRC ST on ST.SHIFTASSIGNID = SA.SHIFTASSIGNID
LEFT JOIN ACTIONTYPE AT on AT.ACTIONTYPEID = ST.ACTIONTYPEID
LEFT JOIN LABORACCT LA on (LA.LABORACCTID = HA.LABORACCTID)
WHERE
TRUNC(SA.SHIFTSTARTDATE) = :prmMediaDate
AND :prmMediaDate BETWEEN HA.EFFECTIVEDTM AND (HA.EXPIRATIONDTM - 1)
AND ((:prmMediaDate BETWEEN O.EFFECTIVEDTM AND (O.EXPIRATIONDTM - 1)) OR (O.EFFECTIVEDTM IS NULL))
AND (SSOT.SEGMENTNUM = 1 OR SSOT.SEGMENTNUM IS NULL)
AND (TRUNC(SSOT.SHIFTSTARTDATE) = :prmMediaDate OR SSOT.SHIFTSTARTDATE IS NULL)
AND SA.DELETEDSW = 0
AND (O.ODIV = :prmSchdDiv OR LA.LABORLEV1NM = :prmSchdDiv)
AND P.PERSONNUM = :prmSchdAssoc;
end;
/
I have tried multiple options like declaring VARIABLE as var, set Scan ON etc.. But it didnt help.
You need to understand that declare is pl/sql and variable is part of sql*plus program commands.
So to successfully execute that code you need to remove DECLARE command.
Set Serveroutput On;
/* RUN the following as a SCRIPT (F5) */
--DECLARE
Variable Prmmediadate Varchar2(10);
Begin
Select '07/17/2017' Into :Prmmediadate From Dual;
End;
/
print :Prmmediadate
PL/SQL procedure successfully completed.
PRMMEDIADATE
--------------------------------------------------------------------------------
07/17/2017
There's the simplified version of my code who keep raise me ORA-06502:
declare
p_filter varchar2(300) := '2012';
p_value varchar2(300) := '12345.000';
w_new_value number(13,3) := null ;
w_count number(4) := null ;
BEGIN
SELECT count(*)
INTO w_count
FROM dual
where p_filter = p_filter;
--- more filters
if w_count != 0 then
w_new_value := p_value / w_count;
else
w_new_value := p_value;
end if;
-- do something
end;
/
Someone can give me a help?
DataBase Details
nls_language = italian
nls_territory = italy
nls_currency = �
nls_iso_currency = italy
nls_numeric_characters = ,.
nls_calendar = gregorian
nls_date_format = dd-mon-rr
nls_date_language = italian
nls_characterset = we8iso8859p15
nls_sort = west_european
nls_time_format = hh24:mi:ssxff
nls_timestamp_format = dd-mon-rr hh24:mi:ssxff
nls_time_tz_format = hh24:mi:ssxff tzr
nls_timestamp_tz_format = dd-mon-rr hh24:mi:ssxff tzr
nls_dual_currency = �
nls_nchar_characterset = al16utf16
nls_comp = binary
nls_length_semantics = byte
nls_nchar_conv_excp = false
First, this is always going return a value of 1.
SELECT count(*)
INTO w_count
FROM dual
It doesn't matter what the qualifier is.
Lastly, I just ran your simplified code example in Oracle 11R2 and it didn't throw an exception.
I added the following statement in place of your "do something" comment:
dbms_output.put_line('w_new_value: ' || w_new_value || '. w_count: ' || w_count);
The result was:
w_new_value: 12345. w_count: 1
So, I think you've simplified your example into oblivion. You need to provide something that actually shows the error.
Good luck.
I found myself the ansewer and i think is useful for other know.
The real problem of the script for my DB is the language.
The italian "version" of Oracle accept , instead of the . for translate the VARCHAR2 into NUMBER unlike the most of other country.
For make the code running well the solution is
w_new_value := replace(p_value,'.',',') / w_count;
This trick finally allows the DB use my VARCHAR2 param like a NUMBER
Is it possible to do something like this in PL/SQL in 10g?
if user_is_goat = 1 then
for item_rec in (select * from pricing_for_goats)
else
for item_rec in (select * from pricing_for_non_goats)
end if;
loop
.
.
end loop;
It seems that when oracle sees "for rec in select * from dual" it expects "loop" to immediate follow. My code in the loop is many lines and I don't want to have to maintain 2 copies of it.
Try query below, this will check if variable user_is_goat = 1 and returns data from for_goats else it will return from for_non_goats
for item_rec in
(
select * from pricing_for_goats where user_is_goat = 1
union
select * from pricing_for_non_goats where user_is_goat <> 1
)
loop
.....
.....
end loop;
I am using the Oracle SQL Developer Scratch Editor tool. There are a couple of small errors, I am not sure how to fix.
--SQLDEV:Following Line Not Recognized
WHILE #I <= #PAT_CNT
--SQLDEV:Following Line Not Recognized
BEGIN
SELECT PAT_NUMBER ,
PATIENT_ID ,
MRN ,
LAST_NAME ,
FIRST_NAME ,
UNIT_CODE ,
NURSING_UNIT ,
SDT ,
EDT ,
SHIFT_CODE ,
START_TIME ,
END_TIME
INTO v_PAT_NUMBER,
v_PATIENT_ID,
v_MRN,
v_LAST_NAME,
v_FIRST_NAME,
v_UNIT_CODE,
v_NURSING_UNIT,
v_SDT,
v_EDT,
v_SHIFT_CODE,
v_START_TIME,
v_END_TIME
FROM tt_v_PATS
WHERE PKEY = v_I;
BEGIN
v_L_CUR_DATE := TRUNC_DATE(v_P_START_DATE) ;
END;
--SQLDEV:Following Line Not Recognized
WHILE #L_CUR_DATE <= OPTC.TRUNC_DATE(#P_END_DATE)
--SQLDEV:Following Line Not Recognized
BEGIN
It's not obvious to me exactly what you are attempting to do here...
In PL/SQL, variables are declared in the DECLARE section of an anonymous PL/SQL block or in the IS/ AS section of a named PL/SQL block (a stored procedure or a stored function). In PL/SQL, a BEGIN needs to be paired with an END-- I see a bunch of BEGIN statements in your code with no associated END. And in PL/SQL, you don't use # to refer to variables.
Something like this is syntactically valid, it's not obvious that it does what you want, however.
DECLARE
v_PAT_NUMBER tt_v_PATS.PAT_NUMBER%type;
v_PATIENT_ID tt_v_PATS.PATIENT_ID%type;
v_MRN tt_v_PATS.MRN%type;
v_LAST_NAME tt_v_PATS.LAST_NAME%type;
v_FIRST_NAME tt_v_PATS.FIRST_NAME%type;
v_UNIT_CODE tt_v_PATS.UNIT_CODE%type;
v_NURSING_UNIT tt_v_PATS.NURSING_UNIT%type;
v_SDT tt_v_PATS.SDT%type;
v_EDT tt_v_PATS.EDT%type;
v_SHIFT_CODE tt_v_PATS.SHIFT_CODE%type;
v_START_TIME tt_v_PATS.START_TIME%type;
v_END_TIME tt_v_PATS.END_TIME%type;
v_pat_cnt integer := 100;
BEGIN
FOR i IN 1 .. v_pat_cnt
LOOP
SELECT PAT_NUMBER ,
PATIENT_ID ,
MRN ,
LAST_NAME ,
FIRST_NAME ,
UNIT_CODE ,
NURSING_UNIT ,
SDT ,
EDT ,
SHIFT_CODE ,
START_TIME ,
END_TIME
INTO v_PAT_NUMBER,
v_PATIENT_ID,
v_MRN,
v_LAST_NAME,
v_FIRST_NAME,
v_UNIT_CODE,
v_NURSING_UNIT,
v_SDT,
v_EDT,
v_SHIFT_CODE,
v_START_TIME,
v_END_TIME
FROM tt_v_PATS
WHERE PKEY = i;
<<do something with the local variables>>
END LOOP;
END;
Of course, you can also use record types to simplify your code a bit
DECLARE
v_PATS_REC tt_v_PATS%rowype;
v_pat_cnt integer := 100;
BEGIN
FOR i IN 1 .. v_pat_cnt
LOOP
SELECT *
INTO v_PATS_REC
FROM tt_v_PATS
WHERE PKEY = i;
<<do something with the record>>
END LOOP;
END;