Error trying to print Collection variable by index - oracle

Can anyone identify what is wrong with the following code. specifically the first dbms_output line. The second one prints fine. But first one gives this error:
Error at line 2
ORA-06550: line 15, column 53:
PLS-00201: identifier 'MYCOLL' must be declared
ORA-06550: line 15, column 1:
PL/SQL: Statement ignored
DECLARE
CURSOR c1
IS
SELECT sub_provider_address_id sub_id, phone, extension
FROM sub_provider_address;
TYPE coll_type IS TABLE OF c1%ROWTYPE;
my_coll coll_type;
BEGIN
OPEN c1;
FETCH c1
BULK COLLECT INTO my_coll;
dbms_output.put_line(' my_coll first row id has '|| mycoll(1).phone );
dbms_output.put_line(' my_coll now has '|| my_coll.last );
END;

You're declaring the variable as my_coll:
my_coll coll_type;
And on the line that's erroring you're referring to it as mycoll:
dbms_output.put_line(' my_coll first row id has '|| mycoll(1).phone );
So you're just missing an underscore, and it should be:
dbms_output.put_line(' my_coll first row id has '|| my_coll(1).phone );

Your coll_type is not an associated array type.
you have to use something like this:
TYPE coll_type IS TABLE OF c1%ROWTYPE index by pls_integer;
Use this as an example:
declare
cursor c1 is
select 1 id from dual
;
type coll_type is table of c1%ROWTYPE index by pls_integer;
l_coll_type coll_type;
begin
open c1;
fetch c1 bulk collect into l_coll_type;
close c1;
dbms_output.put_line('Output:' || l_coll_type(1).id);
end;
Output:1

Related

Show the output of a procedure in Oracle

The procedure uses the previous function to display the list of the products: num, designation and mention on the application.
SET SERVEROUTPUT ON;
CREATE OR REPLACE FUNCTION STORE(num_produit IN INTEGER) RETURN VARCHAR AS
N INTEGER := 0;
incre INTEGER := 0;
BEGIN
SELECT SUM(qte) INTO N FROM Ligne_Fact WHERE num_produit = produit;
IF N > 15 THEN
RETURN 'fort';
ELSIF N > 11 THEN
RETURN 'moyen';
END IF;
RETURN 'faible';
END;
/
CREATE OR REPLACE PROCEDURE SHOW_PRODUITS IS
SOME_VAR VARCHAR2(256);
BEGIN
SELECT num, designation, STORE(num) INTO SOME_VAR FROM Produit;
dbms_output.enable();
dbms_output.put_line('result : '|| SOME_VAR);
END;
/
BEGIN
SHOW_PRODUITS;
END;
/
I am sure that all the tables are filled with some dummy data, but I am getting the following error:
Function STOCKER compiled
Procedure AFFICHER_PRODUITS compiled
LINE/COL ERROR
--------- -------------------------------------------------------------
4/4 PL/SQL: SQL Statement ignored
4/56 PL/SQL: ORA-00947: not enough values
Errors: check compiler log
Error starting at line : 28 in command -
BEGIN
AFFICHER_PRODUITS;
END;
Error report -
ORA-06550: line 2, column 5:
PLS-00905: object SYSTEM.SHOW_PRODUITS is invalid
ORA-06550: line 2, column 5:
PL/SQL: Statement ignored
06550. 00000 - "line %s, column %s:\n%s"
*Cause: Usually a PL/SQL compilation error.
The first major mistake you've made is to create your objects in SYSTEM schema. It, just like SYS, are special and should be used only for system maintenance. Create your own user and do whatever you're doing there.
As of your question: select returns 3 values, but you're trying to put them into a single some_var variable. That won't work. Either add another local variables (for num and designation), or remove these columns from the select:
CREATE OR REPLACE PROCEDURE SHOW_PRODUITS IS
SOME_VAR VARCHAR2(256);
BEGIN
SELECT STORE(num) INTO SOME_VAR FROM Produit; --> here
dbms_output.enable();
dbms_output.put_line('result : '|| SOME_VAR);
END;
/
Code, as you put it, presumes that produit contains a single record (it can't be empty nor it can have 2 or more rows because you'll get various errors).
Maybe you wanted to access all rows; in that case, consider using a loop, e.g.
CREATE OR REPLACE PROCEDURE SHOW_PRODUITS IS
SOME_VAR VARCHAR2(256);
BEGIN
FOR cur_r IN (SELECT num, designation, STORE(num) some_var FROM Produit) LOOP
dbms_output.put_line(cur_r.num ||', '|| cur_r.designation ||', result : '|| cur_r.some_var);
END LOOP;
END;
/
Then
set serveroutput on
BEGIN
SHOW_PRODUITS;
END;
/
You are trying to compile some stored routine which calls another stored routine named AFFICHER_PRODUITS and that routine calls SHOW_PRODUITS but SHOW_PRODUITS does not compile, hence the error. (By the way, it is recommended not to create your own stored routines in the SYSTEM schema.)
SHOW_PRODUITS does not compile because of this line:
SELECT num, designation, STORE(num) INTO SOME_VAR FROM Produit;
It appears that you want to get the query results as a string. In order to do that, you need to concatenate the column values, i.e.
SELECT num || designation || STORE(num) INTO SOME_VAR FROM Produit;
Of-course if all you want to do is display the query results, using DBMS_OUTPUT, you can declare a separate variable for each column.
CREATE OR REPLACE PROCEDURE SHOW_PRODUITS IS
SOME_NUM Produit.num%type;
SOME_DES Produit.designation%type;
SOME_VAR VARCHAR2(6);
BEGIN
SELECT num
,designation
,STORE(num)
INTO SOME_NUM
,SOME_DES
,SOME_VAR
FROM Produit;
dbms_output.enable();
dbms_output.put_line('result : ' || SOME_NUM || SOME_DES || SOME_VAR);
END;
Note that if the query returns more than one row, you will [probably] need to use a cursor.
CREATE OR REPLACE PROCEDURE SHOW_PRODUITS IS
SOME_NUM Produit.num%type;
SOME_DES Produit.designation%type;
SOME_VAR VARCHAR2(6);
--
CURSOR c1 IS
SELECT num, designation, STORE(num) FROM Produit;
BEGIN
OPEN c1;
LOOP
FETCH c1 INTO SOME_NUM, SOME_DES, SOME_VAR;
EXIT WHEN c1%NOTFOUND;
dbms_output.put_line('result : ' || SOME_NUM || SOME_DES || SOME_VAR);
END LOOP;
CLOSE c1;
END;

Error while compiling cursor in plsql block

I have a table as employee. I am new to oracle.I am creating the cursor but when I compile,I get error:
DECLARE
CURSOR c_data IS
SELECT distinct dept_id
FROM offc.employee;
tmp_event offc.employee.dept_id%type;
BEGIN
OPEN c_data;
LOOP
FETCH c_data INTO tmp_event;
EXIT WHEN c_data%NOTFOUND;
Dbms_Output.Put_Line(tmp_event.dept_id);
END LOOP;
CLOSE c_data;
END;
/
I got the error as follows:
Error at line 1 ORA-06550: line 15, column 40: PLS-00487: Invalid
reference to variable 'TMP_EVENT' ORA-06550: line 15, column 9:
PL/SQL: Statement ignored
I think there is problem in tmp_event declaration.How to handle this error?
You should use Dbms_Output.Put_Line(tmp_event);
where tmp_event is a variable which is already of type offc.employee.dept_id%type
This link would help for details.
Try Below Query
DECLARE
CURSOR c_data IS
SELECT distinct dept_id
FROM offc.employee;
tmp_event offc.employee.dept_id%type;
BEGIN
OPEN c_data;
LOOP
FETCH c_data INTO tmp_event;
EXIT WHEN c_data%NOTFOUND;
dbms_output.Put_line(tmp_event); --Dont Use Dept id
END LOOP;
CLOSE c_data;
END;
/
The following PL/SQL statement is equivalent to the original statement, but way shorter and thus less prone to programming errors.
DECLARE
CURSOR c_data IS
SELECT DISTINCT dept_id
FROM offc.employee;
BEGIN
FOR r_data IN c_data LOOP
Dbms_Output.Put_Line(r_data.dept_id);
END LOOP;
END;
/

PL/SQL FIRST LAST EXISTS - (cannot show table contents)

First, I have read the PL/SQL documentation repeatedly, no help. Second, I have googled for hours (usually being led here) and still cannot figure this out.
I have created an index table, which seems to have been successful - at least it did not throw any errors...
DECLARE
CURSOR cur_emps IS
SELECT employee_id, last_name, job_id, salary FROM employees ORDER BY employee_id;
TYPE t_emp_rec IS TABLE OF cur_emps%ROWTYPE
INDEX BY BINARY_INTEGER;
v_emp_rec_tab t_emp_rec;
BEGIN
FOR emp_rec IN cur_emps LOOP
v_emp_rec_tab(emp_rec.employee_id) := emp_rec;
END LOOP;
However, when I try to show what is in my index table. I fail...
Documentation says do something like this...
DECLARE
CURSOR cur_emps IS
SELECT employee_id, last_name, job_id, salary FROM employees ORDER BY employee_id;
TYPE t_emp_rec IS TABLE OF cur_emps%ROWTYPE
INDEX BY BINARY_INTEGER;
v_emp_rec_tab t_emp_rec;
BEGIN
FOR emp_rec IN cur_emps LOOP
v_emp_rec_tab(emp_rec.employee_id) := emp_rec;
END LOOP;
FOR i IN v_emp_rec_tab.FIRST..v_emp_rec_tab.LAST LOOP
IF v_emp_rec_tab.EXISTS(i)
THEN DBMS_OUTPUT.PUT_LINE(v_emp_rec_tab(i));
END IF;
END LOOP;
END;
... which gives me this...
ORA-06550: line 13, column 12:
PLS-00306: wrong number or types of arguments in call to 'PUT_LINE'
ORA-06550: line 13, column 12:
PL/SQL: Statement ignored
In place of
THEN DBMS_OUTPUT.PUT_LINE(v_emp_rec_tab(i));
. I have tried
emp_rec.last_name, v_emp_rec.last_name, cur_emps.last name
... it has been days now trying, can anyone help?
Thanks.
Daniel
You should iterate over an indexed table like this:
l_idx := v_emp_rec_tab.first;
while (l_idx is not null) loop
dbms_output.put_line( v_emp_rec_tab(l_idx).last_name );
l_idx := v_emp_rec_tab.next(l_idx);
end loop;
Otherwise you will get an exception when your table indexes are not consecutive.
See here
v_emp_rec_tab is of rowtype, and it's not possible to call as
DBMS_OUTPUT.PUT_LINE(v_emp_rec_tab(i));
but you can call as :
DBMS_OUTPUT.PUT_LINE(v_emp_rec_tab(i).last_name);
with only one column or you might concatenate like :
DBMS_OUTPUT.PUT_LINE(v_emp_rec_tab(i).last_name||' '||v_emp_rec_tab(i).employee_id);
for multiple columns.

Run stored procedure in SQL Developer

I have procedure with params:
procedure GetReceipt(iPaymentID in number
,oReceipt out sys_refcursor
,oReceiptItems out sys_refcursor);
I try to run this my anonymous block:
SET serveroutput on;
DECLARE
oReceipt sys_refcursor;
oReceiptItems sys_refcursor;
BEGIN
API.MOD.GetReceipt(4209735, oReceipt, oReceiptItems);
dbms_output.put_line('oReceipt: ' || oReceipt);
dbms_output.put_line('oReceiptItems: ' || oReceiptItems);
END;
I get this error:
Error report:
ORA-06550: Строка 6, столбец 24:
PLS-00306: wrong number or types of arguments in call to '||'
ORA-06550: Строка 6, столбец 3:
PL/SQL: Statement ignored
ORA-06550: Строка 7, столбец 24:
PLS-00306: wrong number or types of arguments in call to '||'
ORA-06550: Строка 7, столбец 3:
PL/SQL: Statement ignored
06550. 00000 - "line %s, column %s:\n%s"
*Cause: Usually a PL/SQL compilation error.
*Action:
How call this procedure? Where my mistake?
You can use bind variables to store the cursors and PRINT to print them:
VARIABLE receipt REFCURSOR;
VARIABLE receiptitems REFCURSOR;
BEGIN
API.MOD.GetReceipt(4209735, :receipt, :receiptitems);
END;
/
PRINT receipt;
PRINT receiptitems;
Where my mistake?
A cursor is a named pointer to a private SQL area that stores information for processing a specific query. It does not make sense to concatenate a pointer to something internal to the database with a string.
If you want to display the values in your PL/SQL block then you will need to loop through each record of the cursor and get the individual column values for that record and then use DBMS_OUTPUT to display them:
SET serveroutput on;
DECLARE
oReceipt sys_refcursor;
oReceiptItems sys_refcursor;
col1 RECEIPT_TABLE.COL1%TYPE; -- Same data type as COL1 of the RECEIPT_TABLE table
col2 RECEIPT_TABLE.COL2%TYPE; -- Same data type as COL2 of the RECEIPT_TABLE table
col3 RECEIPT_TABLE.COL3%TYPE; -- Same data type as COL3 of the RECEIPT_TABLE table
rec RECEIPT_ITEMS_TABLE%ROWTYPE; -- Assumes the cursor is returning all the columns from
-- the RECEIPT_ITEMS_TABLE table
BEGIN
API.MOD.GetReceipt(4209735, oReceipt, oReceiptItems);
dbms_output.put_line('oReceipt:');
LOOP
FETCH oReceipt INTO col1, col2, col3; -- Store the values from the current record
EXIT WHEN oReceipt%NOTFOUND; -- Stop if the end of the cursor has been reached
DBMS_OUTPUT.PUT_LINE( col1 || ' ' || col2 || ' ' || col3 );
-- Output the values
END LOOP;
dbms_output.put_line('oReceiptItems:');
LOOP
FETCH oReceiptItems INTO rec; -- Fetch the current row into a record
EXIT WHEN oReceipt%NOTFOUND;
DBMS_OUTPUT.PUT_LINE( rec.colA || ' ' || rec.colB || ' ' || rec.colC );
END LOOP;
END;
/
sys_refcursor returns record set, may not be just a column.
So, you can not message it as a classical string with dbms_output.put_line. There should exists some columns(sub-components) of this argument in your routine like oReceiptItems.col_a or oReceiptItems.col_b so that you could message by these columns as strings with dbms_output.put_line.

Dynamic column name using cursor in Oracle PLSQL

I need to generate the column name dynamically in loop and access the column in oracle table using PLSQL. How do I do that?
DECLARE
varValue VARCHAR(20);
CURSOR c IS
SELECT * FROM TEST1;
BEGIN
FOR i IN c LOOP
FOR j IN 1..5
LOOP
EXECUTE IMMEDIATE 'SELECT ''NAME1'||to_Char(j)||''' from dual' INTO varValue;
dbms_output.put_line(j);
dbms_output.put_line(i.varValue);
END LOOP;
END LOOP;
END;
Actual issue is, I need to acccess the cell values of each row (i) given by cursor (c) like i.name11, i.name12....i.name1100. The logic to be deployed in each cell is same. So i need the column name used here i.e. name11 to be generated dynamically. That is alread done and stored to a variable varValue. Now how can i access the cells i.varValue such that var value is generated in the loop.
The error is as follows:
ORA-06550: line 14, column 34:
PLS-00302: component 'VARVALUE' must be declared
ORA-06550: line 14, column 11:
PL/SQL: Statement ignored
DECLARE
varValue VARCHAR(20);
CURSOR c IS
SELECT * FROM TEST1;
BEGIN
FOR i IN c LOOP
FOR j IN 1..5
LOOP
EXECUTE IMMEDIATE 'SELECT ''NAME1'||to_Char(j)||''' from dual' INTO varValue;
dbms_output.put_line(j);
dbms_output.put_line('NAME1'||to_Char(j)||' : '||varValue);
END LOOP;
END LOOP;
END;

Resources