How to join 2 tables in PLSQL in ORACLE APEX - oracle

I am trying to create a form with dynamic region for purposes of printing. I have a simple PLSQL that works:
declare
cursor c_VYDEJKY is
select ID, INFO, CUSTOMER_ID
from VYDEJKY
where ID = :P54_NEW;
begin
sys.htp.p('<ul>');
for a in c_VYDEJKY loop
sys.htp.p('<li>' || a.ID || ' (' || a.CUSTOMER_ID || ')</li>' );
end loop;
sys.htp.p('</ul>');
end;
but when I try to join another table with LEFT JOIN or WHERE clause it doesnt work:
declare
cursor c_VYDEJKY is
select v.ID, v.INFO, v.CUSTOMER_ID, c.CUSTOMERNAME
from VYDEJKY v, CUSTOMERS c
where v.ID = :P54_NEW
AND v.CUSTOMER_ID > c.ID;
begin
sys.htp.p('<ul>');
for a in c_VYDEJKY loop
sys.htp.p('<li> ID VÝDEJKY :' || a.ID ||'</li>' );
sys.htp.p('<li> POZNÁMKY :' || a.INFO ||'</li>' );
sys.htp.p('<li> POZNÁMKY :' || c.CUSTOMERNAME ||'</li>' );
end loop;
sys.htp.p('</ul>');
end;
I am getting following error on c.CUSTOMERNAME
ORA-06550: line 15, column 39: PLS-00201: identifier 'C.CUSTOMERNAME' must be declared
Can someone please point to where I am makiing a mistake. I am really just starting with PLSQL.
Thank you,
JJ

Within the for loop, the prefix for the column names refers to the cursor row variable (for a in) not the table alias, so you need to specify:
a.CUSTOMERNAME

Related

Procedure parameter determines nested procedure parameter

I am wanting to write a procedure that takes an invoice number and then outputs the details of the customer that bought that particular product.
I have a procedure that displays the details of the customer using a id number as a parameter and that works fine!
I don't know how to use the invoice number to determine the ID value for the customer procedure.
Am using Oracle, sql plus
Code:
Customer details procedure:
SET SERVEROUTPUT ON;
CREATE OR REPLACE PROCEDURE custdets (in_number IN customers.c_ID%TYPE)
IS
CURSOR customer_cursor
IS
SELECT c_ID,
C_PH,
c_FName,
c_LName,
c_address1,
c_address2,
c_address3
FROM customers
WHERE in_number = c_id;
crow customer_cursor%ROWTYPE;
BEGIN
FOR crow IN customer_cursor
LOOP
DBMS_OUTPUT.PUT_LINE ('Customer Details');
DBMS_OUTPUT.PUT_LINE (
'CUST ID#: ' || crow.c_id || CHR (9) || 'PH: ' || crow.c_ph);
DBMS_OUTPUT.PUT_LINE (
'Customer Name: ' || crow.c_Fname || ',' || crow.c_Lname);
DBMS_OUTPUT.PUT_LINE (
'Address: '
|| crow.c_address1
|| ','
|| crow.c_address2
|| ','
|| crow.c_address3);
END LOOP;
EXCEPTION
WHEN OTHERS
THEN
DBMS_OUTPUT.PUT_LINE (SQLERRM);
END;
/
Current Query:
CREATE OR REPLACE PROCEDURE SalePurchase(in_invoice IN sales_purchases.sp_invoice%TYPE)
IS
BEGIN
DBMS_OUTPUT.PUT_LINE('###########################################');
DBMS_OUTPUT.PUT_LINE('# P U R H A S E - S A L E - S U M M A R Y #');
DBMS_OUTPUT.PUT_LINE('# INVOICE NO: ' || in_invoice || ' #');
DBMS_OUTPUT.PUT_LINE(chr(13));
DBMS_OUTPUT.PUT_LINE('###########################################');
DBMS_OUTPUT.PUT_LINE(CHR(13));
DBMS_OUTPUT.PUT_LINE('############################################');
custdets();
end;
/
Thanks in advance!
Edit:
Have worked out that when i place an ID number in the procedure i want to call, eg custdets(4), it prints out the customer with the ID of that number. This is regardless of if they made the purchase or not.
Invoice number should be the primary key of, I don't know, a table called INVOICES maybe? It's your schema, you know it better than we can. Anyhow, that table should have a column called C_ID or perhaps customer_id which is the ID of the customer being invoiced; that column is a foreign key to the CUSTOMERS table.
So, your new procedure must take Invoice ID as a parameter. Use that value to look up the INVOICES record. That will give you the C_ID to pass into your existing custdets() procedure and display the Customer details.
"They are both in the same table how do i pass it it to custdets()"
Something like this:
CREATE OR REPLACE PROCEDURE SalePurchase(
in_invoice IN sales_purchases.sp_invoice%TYPE)
IS
l_customer_id sales_purchases.c_id%type;
BEGIN
select c_id into l_customer_id
from sales_purchases
where sp_invoice = in_invoice;
custdets(l_customer_id);
END;

How do I fix my procedure country_demographics?

CREATE OR REPLACE PROCEDURE country_demographics
(p_country_name IN countries.country_name%TYPE,
p_country_demo_rec OUT ed_type)
IS
TYPE ed_type IS RECORD (
c_name countries.country_name%TYPE,
c_location countries.location%TYPE,
c_capitol countries.capitol%TYPE,
c_population countries.population%TYPE,
c_airports countries.airports%TYPE,
c_climate countries.climate%TYPE);
BEGIN
SELECT country_name, location, capitol, population, airports, climate
INTO ed_type.c_name, ed_type.c_location, ed_type.c_capitol, ed_type.population, ed_type.airports, ed_type.climate
FROM countries;
DBMS_OUTPUT.PUT_LINE('Country Name:' || v_country_demo_rec.country_name ||
'Location:' || v_country_demo_rec.location ||
'Capitol:' || v_country_demo_rec.capitol ||
'Population:' || v_country_demo_rec.population ||
'Airports:' || v_country_demo_rec.airports ||
'Climate:' || v_country_demo_rec.climate );
IF SQL%NOTFOUND THEN
RAISE_APPLICATION_ERROR(-20201, 'This country does not exist.');
END IF;
END;
The problem is asking me to create a procedure called country_demograhics. Pass the country_name as an IN parameter. Display CONTRY_NAME, LOCATION, CAPITOL, POPULATION, AIRPORTS, CLIMATE. Use a user-defined record structure for the INTO clause of your select statement. Raise an exception if the country does not exist.
Now here is a copy of my code, that keeps coming back with an error of:
Error at line 0: PL/SQL: Compilation unit analysis terminated.
That error should be the second error which tells you, it will not look any further. There should be another error too. I guess that ed_type doesn't exist outside of the procedure so it can not have an ed_type as OUT parameter. ed_type isn't known outside.
First thing - Look you used the different variable in declaring(p_country_demo_rec ) and begin(v_country_demo_rec) part. I think that might be one mistake.
Try following script:- it may help you.
CREATE OR REPLACE PROCEDURE COUNTRY_DEMOGRAPHICS
IS
TYPE ED_TYPE IS TABLE OF countries%ROWTYPE;
p_country_demo_rec ED_TYPE;
BEGIN
SELECT * BULK COLLECT INTO p_country_demo_rec FROM countries;
FOR i IN p_country_demo_rec.FIRST..p_country_demo_rec.LAST
LOOP
DBMS_OUTPUT.PUT_LINE('Country Name:'||p_country_demo_rec(i).country_name ||
'Location:' || p_country_demo_rec(i).location ||
'Capitol:' || p_country_demo_rec(i).capitol ||
'Population:' || p_country_demo_rec(i).population ||
'Airports:' || p_country_demo_rec(i).airports ||
'Climate:' || p_country_demo_rec(i).climate );
END LOOP;
IF SQL%NOTFOUND THEN
RAISE_APPLICATION_ERROR(-20201, 'This country does not exist.');
END IF;
END;
/
EXECUTE COUNTRY_DEMOGRAPHICS;
Note:- You can use the one parameter(IN parameter) in a procedure to get the specific country demographics data and that parameter use in select statement for filter out the specific country.
Example:
CREATE OR REPLACE PROCEDURE COUNTRY_DEMOGRAPHICS(p_country_name IN varchar2)
Select statement looks like:
SELECT * BULK COLLECT INTO p_country_demo_rec FROM countries where
country_name = ||p_country_name;
Execute part:
EXECUTE COUNTRY_DEMOGRAPHICS(p_country_name);

Error in pl/sql block has me stuck - Number and/or types of columns in a query does not match

Not quite sure what I am doing wrong here, went over the code a few times tonight and I think I need a fresh set of eyes. I keep getting an error that states:
*Cause: Number and/or types of columns in a query does not match declared
return type of a result set variable, or declared types of two Result
Set variables do not match.
*Action: Change the program statement or declaration. Verify what query the variable
actually refers to during execution.
DECLARE
cv_prod SYS_REFCURSOR;
rec_payment dd_payment%ROWTYPE;
TYPE pay2 IS RECORD (
pledge_id dd_pledge.idpledge%TYPE,
amount NUMBER(8,2)
);
rec_payment2 pay2;
lv_donor_id dd_donor.iddonor%TYPE := 303;
lv_indicator_value CHAR(1) := 'd';
BEGIN
IF lv_indicator_value = 'd' THEN
OPEN cv_prod FOR
SELECT idpledge, payamt, paydate, paymethod
FROM dd_pledge inner join dd_payment USING (idpledge)
WHERE iddonor = lv_donor_id
ORDER BY idpledge, paydate;
LOOP
FETCH cv_prod INTO rec_payment;
EXIT WHEB cv_prod%NOTFOUND;
dbms_output.put_line(rec_payment.idpledge || ' ' || rec_payment.payamt || ' ' || rec_payment.paydate || ' ' || rec_payment.paymethod);
END LOOP;
ELSIF Lv_Indicator_Value = 's' THEN
OPEN cv_Prod FOR
SELECT idpledge, payamt, paydate, paymethod
FROM dd_pledge INNER JOIN dd_payment USING (idpledge)
WHERE iddonor = lv_donor_id
GROUP BY idpledge;
LOOP
FETCH cv_prod INTO rec_payment2;
EXIT WHEN cv_prod%NOTFOUND;
dbms_output.put_line(rec_payment2.pledge_id || ' ' || rec_payment2.amount);
END LOOP;
END IF;
END;
You're collecting the fields selected by your query into a record which doesn't have the same number and type of fields of your query.
For example, in your second cursor you're selecting the fields idpledge, payamt, paydate, paymethod:
OPEN cv_prod FOR
SELECT idpledge, payamt, paydate, paymethod
FROM dd_pledge INNER JOIN dd_payment USING (idpledge)
WHERE iddonor = lv_donor_id
GROUP BY idpledge;
And you're trying to put them into the rec_payment2 record:
FETCH cv_prod INTO rec_payment2;
But the type of this record is pay2, which is a record with only two fields:
TYPE pay2 IS RECORD (
pledge_id dd_pledge.idpledge%TYPE,
amount NUMBER(8,2)
);

Insertion from cursor failing due to data error, How to find the problematic data?

I have cursor which is selecting data and it is running quite fine
CURSOR Crs_c1 IS
SELECT a.GLOBAL_ACCOUNT_CODE,
a.LOCAL_ACCOUNT_CODE,
a.LOCAL_ACCOUNT_NAME,
c.GLOBAL_ACCOUNT_TYPE t_conto,
ltrim(rtrim(a.GLOBAL_ACCOUNT_CODE))||ltrim(rtrim(a.LOCAL_ACCOUNT_CODE)) GLOBAL_LOCAL
FROM V_LOCAL_ACCOUNTS#GDW_LIVE a,V_GLOBAL_ACCOUNTS#GDW_LIVE c --V_LOCAL_ACCOUNTS#GDWPP_ANY a,V_GLOBAL_ACCOUNTS#GDWPP_ANY c
WHERE a.enabled_flag = 'Y'
AND a.GLOBAL_ACCOUNT_CODE=c.GLOBAL_ACCOUNT_CODE
AND not exists (SELECT 1
FROM conto_gdw b -- considero solo i conti nuovi
WHERE a.LOCAL_ACCOUNT_CODE = b.c_conto_local_gdw
AND a.GLOBAL_ACCOUNT_CODE=b.C_CONTO_GLOBAL_GDW);
But at the time of insertion the code fails....
INSERT INTO conto_gdw
(C_CONTO_LOCAL_GDW,
S_CONTO_LOCAL_GDW,
C_CONTO_GLOBAL_GDW,
T_CONTO,
D_INIZIO,
GLOBAL_LOCAL)
VALUES (Rec_Crs_c1.LOCAL_ACCOUNT_CODE,
nvl(Rec_Crs_c1.LOCAL_ACCOUNT_NAME,'.'),
Rec_Crs_c1.GLOBAL_ACCOUNT_CODE,
Rec_Crs_c1.t_conto,
(v_anno_in * 100) + v_mese_in,
Rec_Crs_c1.GLOBAL_LOCAL);
May be this problem is occuring because of a single tuple (dataset). How can I find that culprit data?
I have checked all the data from cursor selection by taking it in a excel sheet, I could not find anything manually. Is there any way ORACLE would return me the failed data?
You need to have a proper exception handling while inserting data .Provide the output of the pl sql block .After than we can help you.
DECLARE
CURSOR Crs_c1
IS
SELECT a.GLOBAL_ACCOUNT_CODE,
a.LOCAL_ACCOUNT_CODE,
a.LOCAL_ACCOUNT_NAME,
c.GLOBAL_ACCOUNT_TYPE t_conto,
LTRIM (RTRIM (a.GLOBAL_ACCOUNT_CODE))
|| LTRIM (RTRIM (a.LOCAL_ACCOUNT_CODE))
GLOBAL_LOCAL
FROM V_LOCAL_ACCOUNTS#GDW_LIVE a, V_GLOBAL_ACCOUNTS#GDW_LIVE c
WHERE a.enabled_flag = 'Y'
AND a.GLOBAL_ACCOUNT_CODE = c.GLOBAL_ACCOUNT_CODE
AND NOT EXISTS
(SELECT 1
FROM conto_gdw b -- considero solo i conti nuovi
WHERE a.LOCAL_ACCOUNT_CODE = b.c_conto_local_gdw
AND a.GLOBAL_ACCOUNT_CODE =
b.C_CONTO_GLOBAL_GDW);
Rec_Crs_c1 Crs_c1%ROWTYPE;
BEGIN
OPEN Crs_c1;
LOOP
FETCH Crs_c1 INTO Rec_Crs_c1;
EXIT WHEN Crs_c1%NOTFOUND;
INSERT INTO conto_gdw (C_CONTO_LOCAL_GDW,
S_CONTO_LOCAL_GDW,
C_CONTO_GLOBAL_GDW,
T_CONTO,
D_INIZIO,
GLOBAL_LOCAL)
VALUES (Rec_Crs_c1.LOCAL_ACCOUNT_CODE,
NVL (Rec_Crs_c1.LOCAL_ACCOUNT_NAME, '.'),
Rec_Crs_c1.GLOBAL_ACCOUNT_CODE,
Rec_Crs_c1.t_conto,
(v_anno_in * 100) + v_mese_in,
Rec_Crs_c1.GLOBAL_LOCAL);
END LOOP;
CLOSE Crs_c1;
EXCEPTION
WHEN OTHERS
THEN
DBMS_OUTPUT.put_line ('Error Message' || SQLERRM);
DBMS_OUTPUT.put_line( 'GLOBAL_ACCOUNT_CODE :'
|| Rec_Crs_c1.LOCAL_ACCOUNT_CODE
|| 'LOCAL_ACCOUNT_CODE '
|| Rec_Crs_c1.LOCAL_ACCOUNT_NAME
|| 'GLOBAL_ACCOUNT_CODE :'
|| Rec_Crs_c1.GLOBAL_ACCOUNT_CODE
|| 'GLOBAL_ACCOUNT_TYPE '
|| Rec_Crs_c1.t_conto
|| 'GLOBAL_LOCAL'
|| Rec_Crs_c1.GLOBAL_LOCAL);
END;

oracle Stored Procedure to get the sum(balance) given a parameter

I have a supplier_product table ( supp_id, prod_id, invoice_id,price) and an invoice table (invoice_id, balance). I tried a stored proc. given (supp_id) it should all the existing invoice_id and display the balance. here's my code:
set serverouput on;
create or replace
Procedure SUP_loop
(v_SUPPLIER_ID int )
AS
CURSOR c_SUP IS
select SUPPLIER_ID , SUPP_INVOICE_ID, balance
from SUPPLIER_PRODUCT, supplier_invoice
where SUPPLIER_ID=v_SUPPLIER_ID
and supp_invoice_id.supplier_product=supp_invoice_id.supplier_invoice;
BEGIN
--LOOP WITH IMPLICIT VARIABLE DECLARED
--AUTOMATIC, OPEN FETCH, CLOSE
FOR v_SUP_data IN c_SUP LOOP
DBMS_OUTPUT.PUT_LINE(TO_CHAR(v_SUP_data.SUPPLIER_ID) || ' ' ||
TO_CHAR(v_SUP_data.SUPP_INVOICE_ID) || ' ' ||
TO_CHAR(v_SUP_data.balance) );
END LOOP;
END;
/
the error i am getting is v_sup_data Error(20,31): PLS-00364: loop index variable 'V_SUP_DATA' use is invalid
Error(9,74): PL/SQL: ORA-00904: "SUPP_INVOICE_ID"."SUPPLIER_INVOICE": invalid identifier
You have the field and the table names swapped round the wrong way.
You have...
supp_invoice_id.supplier_invoice
...where you should have...
supplier_invoice.supp_invoice_id
:D
The syntax for referring to a column is <>.<>. So your cursor query needs the join condition to be supplier_produce.supp_invoice_id = supplier_invoice.supp_invoice_id, i.e.
create or replace
Procedure SUP_loop
(v_SUPPLIER_ID int )
AS
CURSOR c_SUP IS
select SUPPLIER_ID , SUPP_INVOICE_ID, balance
from SUPPLIER_PRODUCT, supplier_invoice
where SUPPLIER_ID=v_SUPPLIER_ID
and supplier_product.supp_invoice_id = supplier_invoice.supp_invoice_id;
BEGIN
--LOOP WITH IMPLICIT VARIABLE DECLARED
--AUTOMATIC, OPEN FETCH, CLOSE
FOR v_SUP_data IN c_SUP LOOP
DBMS_OUTPUT.PUT_LINE(TO_CHAR(v_SUP_data.SUPPLIER_ID) || ' ' ||
TO_CHAR(v_SUP_data.SUPP_INVOICE_ID) || ' ' ||
TO_CHAR(v_SUP_data.balance) );
END LOOP;
END;
/

Resources