I'm trying to use a variable from a cursor in the select statement of another cursor in pl/sql - sql

I need to run a query that finds me the first 20 vehicles that are as close to another vehicle with specific terms. I'm writing this in SQL Developer on an oracle database.
Here's what I have so far:
DECLARE
TYPE cur_type IS REF CURSOR;
CURSOR lost_vehicles_cur IS
select
v.vin,
V.VEHICLE_ID
from d_vehicles V
where v.system_id =4 ;
make_cur cur_type;
l_cur_string VARCHAR2(2000);
l_make <type>;
l_model <type>;
l_vin <type>;
BEGIN
FOR vehicle IN lost_vehicles_cur LOOP
dbms_output.put_line('lost vehicle is '|| vehicle.vehicle_id);
l_cur_string := 'SELECT make_name, model_name,vin FROM vehicles where make=(select make from vehicles where vehicle_id= '
|| vehicle.vehicle_id || 'and rownum<=20 and system_id=3 and vehicle_status_id in (13,14) ';
OPEN make_cur FOR l_cur_string;
LOOP
FETCH make_cur INTO l_make, l_model, L_vin;
EXIT WHEN make_cur%NOTFOUND;
dbms_output.put_line('Related vehicles are ' || l_make || l_model || L_vin);
END LOOP;
CLOSE make_cur;
END LOOP;
END;
I used a previous answer to get to this however I get the following error when I run this:
ORA-06550: line 32, column 13: PLS-00103: Encountered the symbol "<" when expecting one of the following: constant exception table long double ref char time timestamp interval date binary national character nchar 06550. 00000 - "line %s, column %s:\n%s" *Cause: Usually a PL/SQL compilation error. –

You have to use parametrized cursor or dbms_sql:
DECLARE
TYPE cur_type IS REF CURSOR;
CURSOR lost_vehicles_cur IS
select
v.vin,
V.VEHICLE_ID
from d_vehicles V
where v.system_id =4 ;
cursor l_cur (ip_id in d_vehicles.VEHICLE_ID%type)
SELECT make_name, model_name,vin
FROM vehicles
where make in (select make
from vehicles
where vehicle_id= ip_id
and rownum<=20
and system_id=3
and vehicle_status_id in (13,14));
make_cur cur_type;
l_cur_string VARCHAR2(2000);
l_make <type>;
l_model <type>;
l_vin <type>;
BEGIN
FOR vehicle IN lost_vehicles_cur LOOP
dbms_output.put_line('lost vehicle is '|| vehicle.vehicle_id);
OPEN make_cur FOR l_cur (vehicle.vehicle_id);
LOOP
FETCH make_cur INTO l_make, l_model, L_vin;
EXIT WHEN make_cur%NOTFOUND;
dbms_output.put_line('Related vehicles are ' || l_make || l_model || L_vin);
END LOOP;
CLOSE make_cur;
END LOOP;
END;

Related

SQL Invalid Identifier when using bind variable

Using my anonymous block I have written below, the bind variable is giving me the error: I've pasted a picture of the table below.
edit: ETHI1022 is the input I'm giving for the CORID
v_corid CHAR(8) := ETHI1022;
*
ERROR at line 3:
ORA-06550: line 3, column 24:
PLS-00201: identifier 'ETHI1022' must be declared
ORA-06550: line 0, column 0:
PL/SQL: Compilation unit analysis terminated
I realize my inner join is most likely messed up like no other. I'm trying to learn this stuff and am having a very hard time learning how taking values from the select statement and placing them into the variables in the declare section works.
DECLARE
v_marstuid MARKS.STUID%TYPE;
v_corid CHAR(8) := &corid;
v_avgmark NUMBER(2);
v_maxmark NUMBER(2);
v_minmark NUMBER(2);
v_cordesc VARCHAR2(255);
ex_CourseNotFound EXCEPTION;
BEGIN
SELECT Count(M.stuid),
M.corid,
Avg(M.mark),
Max(M.mark),
Min(M.mark),
C.descript
INTO v_marstuid, v_corid, v_avgmark, v_maxmark,
v_minmark, v_cordesc
FROM marks M
inner join courses C
ON M.corid = C.corid
WHERE C.corid = v_corid;
dbms_output.Put_line (v_corid
|| ' - '
|| v_cordesc);
dbms_output.Put_line ('Course Stats: ');
dbms_output.Put_line ('Number of students: '
|| v_marstuid);
dbms_output.Put_line ('Average: '
|| v_avgmark);
dbms_output.Put_line ('Marks Range: ');
dbms_output.Put_line ('High: '
|| v_maxmark);
dbms_output.Put_line ('Low: '
|| v_minmark);
EXCEPTION
WHEN ex_CourseNotFound THEN
DBMS_OUTPUT.PUT_LINE(v_corcode || ' Does not exist.');
END;
/
[Table used]
Instead of ETHI1022 it should be 'ETHI1022'. Your inner join is fine. From where you are getting value of corid. Make it of type varchar/string or something like that.
Or you might try v_corid CHAR(8) := ''''||&corid||'''';

PLS-00103: Encountered the symbol "=" when expecting one of the following.... in PL/SQL script

create or replace function lstnation (listdisplay in varchar2)
return varchar2 is
nName varchar2 (1000) default null;
listD varchar2(1000) default null;
cursor display_nation
is
select nation.n_name
from nation
inner join region
on region.r_regionkey = nation.n_nationkey
where region.r_regionname = listdisplay;
BEGIN
open display_nation;
loop
fetch display_nation into nName;
exit when display_nation%notfound;
IF
listD := listD || RTRIM(nName)||' , ';
end loop;
close display_nation;
return listD;
end lstnation;
/
DECLARE
rKey region.r_regionkey%type;
rName region.r_name%type;
nList varchar2(1000);
cursor outer_block is
select region.r_regionkey, region.r_name, lstnation(region.r_name)
from region;
BEGIN
open outer_block;
loop
fetch outer_block into rKey, rName, nList;
exit when outer_block%notfound;
dbms.output.put_line(rkey || ' ' || RTRIM(rName) || ': '|| nList);
end loop;
close outer_block;
end;
/
I get two errors, how can I fix it
LINE/COL ERROR
19/12 PLS-00103: Encountered the symbol "=" when expecting one of the
following:
. ( * # % & = - + < / > at in is mod remainder not rem then
<an exponent (**)> <> or != or ~= >= <= <> and or like like2
like4 likec between || multiset member submultiset
20/2 PLS-00103: Encountered the symbol "END" when expecting one of the
following:
begin function pragma procedure subtype type
current cursor delete
exists prior
You can save some coding and efficiency by replacing the cursor loop with the listagg function
select listagg(rtrim(nation.n_name),',')
from nation
inner join region
on region.r_regionkey = nation.n_nationkey
where region.r_regionname = listdisplay;
So that will collate all the matching rows, and use whatever delimiter is passed in. One thing to be aware of, you have listD varchar2(1000) so as long as the results from the query are less than 1000, you are OK. If you expect a larger result set, you may need to increase or use a clob.
If for some reason, you still want to use the loop method, then you need to fix your IF statement:
loop
fetch display_nation into nName;
exit when display_nation%notfound;
IF <condition> THEN
listD := listD || RTRIM(nName)||' , ';
END IF;
end loop;

PL/SQL: Cursor doubles the last record from the table

I created the following PL/SQL anonymous block. The cursor below retrieves data from the select statement:
select mod_benutzer, count(*)
from dok_auspraegung
where parent_objekt_id = 1093
group by mod_benutzer;
This statement displays exactly two records:
DDMS_USER | 8
HU2MAMU | 14
But when I want to display these two records by cursor, it displays "HU2MAMU|14" two times like below:
Modifications:
DDMS_USER, 8x
HU2MAMU, 14x
HU2MAMU, 14x
declare
my_exception_1 exception;
var_parent_objekt_id dok_auspraegung.parent_objekt_id%TYPE := 1093;
var_date varchar(30);
var_mod_benutzer varchar2(10);
var_benutzer_modifs number;
cursor cursor_dok_auspraegung
is select mod_benutzer, count(*) from dok_auspraegung
where parent_objekt_id = 10935797565
group by mod_benutzer;
begin
select distinct to_char(mod_datum,'YYYY-MON-DD') into var_date from dok_auspraegung where parent_objekt_id = var_parent_objekt_id;
IF var_date is not null THEN
dbms_output.put_line('Parent Object ID' || ': ' || var_parent_objekt_id);
dbms_output.put_line('Date: ' || ' ' || var_date);
ELSE RAISE my_exception_1;
END IF;
open cursor_dok_auspraegung;
dbms_output.put_line('Modifications:');
loop
fetch cursor_dok_auspraegung into var_mod_benutzer, var_benutzer_modifs;
dbms_output.put(var_mod_benutzer);
dbms_output.put_line(', ' || var_benutzer_modifs || 'x');
exit when cursor_dok_auspraegung%notfound;
end loop;
dbms_output.put_line(cursor_dok_auspraegung%rowcount);
close cursor_dok_auspraegung;
exception
when NO_DATA_FOUND then
dbms_output.put_line('Parent Object ID not found!');
when my_exception_1 then
dbms_output.put_line('');
end;
What is the reason of that?
Because exiting from the cursor occurs after printing the value of the variables in the current case, this repeats the last value to be printed. So, it should occur before printing as follows
loop
fetch cursor_dok_auspraegung into var_mod_benutzer, var_benutzer_modifs;
exit when cursor_dok_auspraegung%notfound;
dbms_output.put(var_mod_benutzer);
dbms_output.put_line(', ' || var_benutzer_modifs || 'x');
end loop;

PLS-00394: Wrong number of values in the INTO list of a fetch statement

This is my attempt in creating a cursor in a stored procedure
--Second Stored Procedure--
CREATE OR REPLACE PROCEDURE sp_GetDiscountedRate (DiscountCode IN
VARCHAR2,Percentage IN NUMBER, ReserveDate IN DATE)
IS --Code declaration section--
--variables to store column values returned from select into
pPassengerID VARCHAR2(10);
pFirst VARCHAR2(20);
pMiddle VARCHAR2(20);
pLast VARCHAR2(20);
pPassengerType CHAR (1);
uUSMilitaryID VARCHAR (8);
uMilitaryBranch VARCHAR2 (20);
uMilitaryDiscountCode VARCHAR2(8);
rFlightNumber VARCHAR2(6);
rReservationCost NUMBER(6);
rReservationDate DATE;
--Declare Cursor
CURSOR cur_USMilitary IS
--Query cursor will point to results
SELECT P.PassengerID, P.First, P.Middle, P.Last, P.PassengerType,
U.USMilitaryID, U.MilitaryBranch,
U.MilitaryDiscountCode, R.FlightNumber, R.ReservationCost,
R.ReservationDate,
CASE U.MilitaryDiscountCode WHEN DiscountCode THEN
Percentage*R.ReservationCost
ELSE R.ReservationCost END "REVISED_RESERVATION_COST"
FROM PASSENGER P, US_Military U, RESERVATION R
WHERE P.PassengerID = U.MPassengerID
AND P.PassengerID = R.PassengerID
AND U.MilitaryDiscountCode = DiscountCode
AND R.ReservationDate = ReserveDate;
--Start Execution section--
BEGIN
--Open Cursor
OPEN cur_USMilitary; -- open cursor for use
--loop to display each record returned by cursor
--Use PL/SQL language control or loop to display each record pointed by cursor
LOOP
--Fetch cursor data
FETCH cur_USMilitary INTO pPassengerID,
pFirst,pMiddle,pLast,pPassengerType,
uUSMilitaryID,uMilitaryBranch,uMilitaryDiscountCode,rFlightNumber,
rReservationCost,rReservationDate;
EXIT WHEN cur_USMilitary%NOTFOUND;
--Display each record
--Displaying the results
DBMS_OUTPUT.PUT_LINE ('CUSTOMER INFORMATION: ');
DBMS_OUTPUT.PUT_LINE ('The PassengerID is: ' ||pPassengerID);
DBMS_OUTPUT.PUT_LINE ('First Name of passenger is: ' ||pFirst);
DBMS_OUTPUT.PUT_LINE ('Middle Name of passenger is: ' ||pMiddle);
DBMS_OUTPUT.PUT_LINE ('Last Name of passenger is: ' ||pLast);
DBMS_OUTPUT.PUT_LINE ('Passenger Type of customer is: ' ||pPassengerType);
DBMS_OUTPUT.PUT_LINE ('US Military ID of Passenger is: ' ||uUSMilitaryID);
DBMS_OUTPUT.PUT_LINE ('Military Branch of passenger is: ' ||uMilitaryBranch);
DBMS_OUTPUT.PUT_LINE ('Military Discount code of passenger is: ' ||uMilitaryDiscountCode);
DBMS_OUTPUT.PUT_LINE ('Flight number of passenger is: ' ||rFlightNumber);
DBMS_OUTPUT.PUT_LINE ('Reservation Cost of passenger is: ' ||rReservationCost);
DBMS_OUTPUT.PUT_LINE ('Reservation Date of passenger is: ' ||rReservationDate);
END LOOP;
CLOSE cur_USMilitary; --close cursor
END sp_GetDiscountedRate;
I get this error:
Error(36,9): PL/SQL: SQL Statement ignored
Error(36,9): PLS-00394: wrong number of values in the INTO list of a FETCH statement
I fully understand the error. I checked the number of columns and it looks like to me that they match the number of columns within the query. I've also checked the datatypes to make sure it was correct.
You have
12 columns in your cursor's SELECT part
but
11 columns in FETCH statement part
, i observe
CASE U.MilitaryDiscountCode WHEN DiscountCode THEN
Percentage*R.ReservationCost
ELSE R.ReservationCost END "REVISED_RESERVATION_COST"
part is missing in FETCH( or should be omitted in the SELECT part ).
It also represents a column, and it spoils 1-1 correspondence, which yields that error.
This is what happens when you overcomplicate things, I'm afraid. I don't see any need for all those variables and the corresponding fetch into that is hard to keep in sync. Why not just:
create or replace procedure sp_getdiscountedrate
( discountcode in varchar2
, percentage in number
, reservedate in date )
is
begin
for r in (
select p.passengerid
, p.first
, p.middle
, p.last
, p.passengertype
, u.usmilitaryid
, u.militarybranch
, u.militarydiscountcode
, r.flightnumber
, r.reservationcost
, r.reservationdate
, case u.militarydiscountcode
when discountcode then percentage * r.reservationcost
else r.reservationcost
end as revised_reservation_cost
from passenger p
join us_military u
on u.mpassengerid = p.passengerid
join reservation r
on r.passengerid = p.passengerid
and r.discountcode = u.militarydiscountcode
and r.reservedate = r.reservationdate
)
loop
dbms_output.put_line('CUSTOMER INFORMATION:');
dbms_output.put_line('The PassengerID is: ' || r.passengerid);
dbms_output.put_line('First Name of passenger is: ' || r.first);
dbms_output.put_line('Middle Name of passenger is: ' || r.middle);
dbms_output.put_line('Last Name of passenger is: ' || r.last);
dbms_output.put_line('Passenger Type of customer is: ' || r.passengertype);
dbms_output.put_line('US Military ID of Passenger is: ' || r.usmilitaryid);
dbms_output.put_line('Military Branch of passenger is: ' || r.militarybranch);
dbms_output.put_line('Military Discount code of passenger is: ' || r.militarydiscountcode);
dbms_output.put_line('Flight number of passenger is: ' || r.flightnumber);
dbms_output.put_line('Reservation Cost of passenger is: ' || r.reservationcost);
dbms_output.put_line('Reservation Date of passenger is: ' || r.reservationdate);
dbms_output.put_line('Revised reservation cost is: ' || r.revised_reservation_cost);
end loop;
end sp_getdiscountedrate;
(Untested)
You go through all the trouble of calculating "REVISED_RESERVATION_COST", and then you don't read it from the cursor.
No wonder Oracle is complaining. You need a variable for this column as well.
I would also advise you to learn to use modern, proper, explicit JOIN syntax.

PLSQL does not compile when substracting two long variables

I'm writing a pretty basic procedure where I need to substract two long variables and assign the value to the other variable. But the code doesn't compile and I am getting hopeless - why is that?
create or replace PROCEDURE TrendCalculator(p_id Prodeje.product%TYPE)
AS
v_week_last Prodeje.WEEK%TYPE;
v_week_current Prodeje.WEEK%TYPE;
v_year_last Prodeje.YEAR%TYPE;
v_year_current Prodeje.YEAR%TYPE;
v_weekly_sales_last PRODEJE.SALES%TYPE;
v_weekly_sales_current PRODEJE.SALES%TYPE;
v_pomocna PRODEJE.SALES%TYPE;
CURSOR c_data IS SELECT WEEK, YEAR, SALES FROM Prodeje WHERE PRODUCT = p_id ORDER BY YEAR, WEEK ASC;
BEGIN
v_pomocna := 0;
OPEN c_data;
LOOP
FETCH c_data INTO v_week_current, v_year_current, v_weekly_sales_current;
EXIT WHEN c_data%NOTFOUND;
IF (v_weekly_sales_last IS NOT NULL) THEN
DBMS_OUTPUT.PUT_LINE(p_id || ' ' || v_week_current || ' ' || v_year_current || ' ' || v_weekly_sales_current);
v_pomocna := (v_weekly_sales_current - v_weekly_sales_last);
END IF;
v_week_last := v_week_current;
v_year_last := v_year_current;
v_weekly_sales_last := v_weekly_sales_current;
END LOOP;
CLOSE c_data;
END;
The Error messages I'm getting are:
Error(19,9): PL/SQL: Statement ignored
Error(19,95): PLS-00306: wrong number or types of arguments in call to '-'
And PRODEJE.SALES Datatype is LONG.
v_weekly_sales_last is not set to anything. So line 19 evaluates to
v_pomocna := (v_weekly_sales_current - );
Which seems to be the cause of your error.