Dynamic column name using cursor in Oracle PLSQL - oracle

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;

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;

Oracle access the record type values using dot notation with identifiers from varray

I am going to access the values from oracle record using the dot notation and identifier as variable, i am getting error V_COL must be declared.
declare
cursor c1 is select * from temp_sample_records;
type t is table of temp_sample_records%rowtype;
l_tab t;
rec c1%rowtype;
term term_cell_data#ktkcm%rowtype;
term_reverify term_cell_data_reverify#ktkcm%rowtype;
type t_cols IS VARRAY(100) OF VARCHAR2(100);
cols t_cols;
V_COL varchar2(100);
begin
cols := t_cols('GSMNUMBER','CAF_SERIAL_NO','CUSTOMER_NAME');
open c1;
loop
fetch c1 bulk collect into l_tab limit 5000;
exit when l_tab.count=0;
for i in l_tab.first..l_tab.last loop
begin
select * into term from term_cell_data#ktkcm where gsmnumber=l_tab(i).msisdn and caf_serial_no=l_tab(i).caf_serial_no;
for c in 1..cols.last loop
V_COL :=cols(c);
dbms_output.put_line(term.V_COL);
end loop;
exception
when no_data_found then null;
end;
end loop;
end loop;
close c1;
end;
/
kindly help where i am making a mistake
Error ORA-06550: line 22, column 51:
PLS-00302: component 'V_COL' must be declared
ORA-06550: line 22, column 25:
PL/SQL: Statement ignored
where i am making a mistake
term.V_COL is not valid as, I am assuming that, you do not have a column named V_COL in the term_cell_data#ktkcm table and you are trying to dynamically access the columns. You cannot do this.
You could look at reflection using ANYDATA, however that does not work with record data types and would need Object data types defined in the SQL scope.
You could also look at the DBMS_SQL package but I think that, even if you worked to get the data using position indexes rather than column names, you would still need to know the data type of every column.
You would probably be best to just statically name each column in the %ROWTYPE variable (rather than trying to dynamically reference columns). So in your inner-most loop, you could use:
select *
into term
from term_cell_data#ktkcm
where gsmnumber=l_tab(i).msisdn
and caf_serial_no=l_tab(i).caf_serial_no;
dbms_output.put_line(term.GSMNUMBER);
dbms_output.put_line(term.CAF_SERIAL_NO);
dbms_output.put_line(term.CUSTOMER_NAME);

Oracle PL/SQL SELECT INTO clause thinks it needs another INTO

I have a simple test function where I'm passing in a specific ID (the primary key of the table I'm selecting from), and computing a simple function on it and the parameters.
The skeleton code and test:
create or replace function test(id varchar2, area float) return float is
theRow forest%ROWTYPE;
begin
select * into theRow from forest where Forest_No = id;
return area / theRow.Area;
end;
begin
select test('1', 16000) from dual;
end;
The output:
[2019-10-14 21:19:10] [65000][6550] ORA-06550: line 2, column 5:
[2019-10-14 21:19:10] PLS-00428: an INTO clause is expected in this SELECT statement
I am at a loss for what to do here, as far as I can tell the documentation and examples use the same order and syntax. I have tried moving the into clause to the end as in Postgresql, but that did not work.
What have I missed here?
Issue is in calling statement.
Whenever select statement is used in plsql block it must have into clause to assign return value to variable.
You should remove begin and end from your calling code:
--begin -- remove this
select test('1', 16000) from dual;
--end; -- remove this
Or if you want to use it in plsql block then add into clause:
Declare
Area_ float(precision);
begin
select test('1', 16000) into area_ from dual;
-- use area_ in your code wherever required
dbms_output.put_line('area: ' || area_);
end;
Cheers!!

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.

Error trying to print Collection variable by index

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

Resources