PLSQL Get Variable By Loop Index - oracle

I am trying to reach columns by loop index of a cursor record. Currently i am using multiple variables for each columns thus I think that I should refactor my codes. In java, I'd use reflection to do that but I stuck in PLSQL. Code will explain better
input is passed into from loop.
i_member_awd_rowtype in member_awd%rowtype
.
.
.
--many more inputs
l_step1_company := i_member_awd_rowtype.flt_company;
l_step1_subclass := i_member_awd_rowtype.class_code;
l_step2_company := i_member_awd_rowtype.ret_flt_company;
l_step2_subclass := i_member_awd_rowtype.ret_class_code;
l_step3_company := i_member_awd_rowtype.step3_company;
l_step3_subclass := i_member_awd_rowtype.step3_class_code;
l_step4_company := i_member_awd_rowtype.step4_company;
l_step4_subclass := i_member_awd_rowtype.step4_class_code;
l_step5_company := i_member_awd_rowtype.step5_company;
l_step5_subclass := i_member_awd_rowtype.step5_class_code;
l_step6_company := i_member_awd_rowtype.step6_company;
l_step6_subclass := i_member_awd_rowtype.step6_class_code;
l_step7_company := i_member_awd_rowtype.step7_company;
l_step7_subclass := i_member_awd_rowtype.step7_class_code;
l_step8_company := i_member_awd_rowtype.step8_company;
l_step8_subclass := i_member_awd_rowtype.step8_class_code;
I need to assign single class, company and subclass variables in a loop such as
/*for i in 1 .. 8 loop
l_step_subclass :=
end loop;*/
Is there any way to write as I wanted in PLSQL? Thanks.

The following code block containing a Dynamic SQL statement might be used, assuming you wanna gather the records for each identity column(id) of the table :
SQL> set serveroutput on
SQL> declare
v_tbl varchar2(31) := 'member_awd';
v_sql varchar2(250);
v_id member_awd.id%type := :p_id;
type typ is table of varchar2(32767) index by binary_integer;
l_step_subclass typ;
begin
for c in ( select column_id, column_name
from user_tab_columns
where table_name = upper(v_tbl) order by column_id )
loop
v_sql := 'select '||c.column_name||' from '||v_tbl||' where id = :i_id ';
execute immediate v_sql into l_step_subclass(c.column_id) using v_id;
dbms_output.put_line(l_step_subclass(c.column_id));
end loop;
end;
/
where the variable l_step_subclass is converted to the array type. This way, all values for each individual column are assigned to this column local variable.

Related

ORA-01008: not all variables bound - "not all variables bound"

This is my plsql block, dynamic SQL. I can't find a reason why it comes up with an error 'no ORA-01008: not all variables bound ORA-06512: at line 23'.
I can't find the error on my EXECUTE IMMEDIATE statement.
DECLARE
form_name VARCHAR2(225) := 'MUST AS';
ad_no VARCHAR2(225) := :ad_no;
sql_stmt VARCHAR2(4000);
sql_output VARCHAR2(4000);
db_table VARCHAR(225) := inp_reminder_pkg.form_db_table(form_name);
col_id VARCHAR(225) := inp_reminder_pkg.get_col_id(form_name);
BEGIN
sql_stmt := '
SELECT :1
FROM #tableName
WHERE advno = :2
AND created = ( SELECT MAX(CREATED)
FROM #tableName
WHERE advno = :2 )'
;
sql_stmt := replace(sql_stmt, '#tableName', db_table);
EXECUTE IMMEDIATE sql_stmt
INTO sql_output
USING col_id, ad_no;
dbms_output.put_line(sql_output);
EXCEPTION
WHEN no_data_found THEN
dbms_output.put_line('no-data');
END;
Let me know what I am missing. thanks you
There are three bind variables (even though two have the same name), you need to send 3 arguments for them in the execute immediate statement.
Note that you probably didn’t mean for the column name to be input as a bind variable, this is something that has to be dynamically executed if you want to have a variable column being selected.
There are two problems with your code:
The dynamic query has two instances of the placeholder :advno so you need to pass two values in the USING clause. Yes this is a bit rubbish, but I guess Oracle felt parsing dynamic SQL is hard enough without asking the compiler to match placeholder names.
We can't pass column names or other identifiers as parameters. We have to break up the statement to reference the column name variable. For the same reason you have the replace() call to substitute the table name.
So you need to change your procedure so it looks like this:
DECLARE
form_name VARCHAR2(225) := 'MUST AS';
ad_no VARCHAR2(225) := :ad_no;
sql_stmt VARCHAR2(4000);
sql_output VARCHAR2(4000);
db_table VARCHAR(225) := inp_reminder_pkg.form_db_table(form_name);
col_id VARCHAR(225) := inp_reminder_pkg.get_col_id(form_name);
BEGIN
sql_stmt := '
SELECT ' || col_id || '
FROM #tableName
WHERE advno = :2
AND created = ( SELECT MAX(CREATED)
FROM #tableName
WHERE advno = :2 )'
;
sql_stmt := replace(sql_stmt, '#tableName', db_table);
EXECUTE IMMEDIATE sql_stmt
INTO sql_output
USING ad_no, ad_no;
dbms_output.put_line(sql_output);
EXCEPTION
WHEN no_data_found THEN
dbms_output.put_line('no-data');
END;

Error PLS-00428: an INTO clause is expected in this SELECT statement

I just want to show USU_USERS table between a declare procedure but it's shows this error when I try to compile
DECLARE
ID_UNICO VARCHAR(200) := 'H3LP';
BEGIN
DECLARE
VID VARCHAR2(200);
VID_USER VARCHAR2(200);
BEGIN
VID := ID_UNICO;
VID_USER := 'SOPORTE';
USR_SP_USERS.CREATE(
VID => VID,
VID_USER => VID_USER,
);
END;
SELECT * from USU_USERS;
END;
NOTE : THIS TABLE HAS MORE THAN ONE ROWS.
PL/SQL is a server-side language only, and as such there's no way to "show" the results of a SELECT statement anywhere. Your SELECT statement needs to put the values it retrieves from the database into a variable or variables. Let's try to give you something which will work:
DECLARE
strID_UNICO VARCHAR(200) := 'H3LP';
strVID VARCHAR2(200);
strVID_USER VARCHAR2(200);
rowUSU_USERS USU_USERS%ROWTYPE;
BEGIN
strVID := strID_UNICO;
strVID_USER := 'SOPORTE';
USR_SP_USERS.CREATE(VID => strVID,
VID_USER => strVID_USER);
SELECT *
INTO rowUSU_USERS
FROM USU_USERS;
END;
Note that if the table USU_USERS has more than one row in it this code will fail. Assuming, though, that USU_USERS has only a single row in it, you could then use DBMS_OUTPUT.PUT_LINE to output the various fields in rowUSU_USERS.

inserting of data not happening in oracle

I am new to plsql.I have a table where i need to insert the data(some dummy data).So,i thought to use plsql block and using For loop it will insert the data automatically.The plsql block is runned successfully,but the data are stored as empty.The block I tried is:
declare
v_number1 number;
v_number2 number;
v_number3 number;
begin
For Lcntr IN 2..17
LOOP
v_number1 := v_number1+1;
v_number2 := v_number2+2;
v_number3 := v_number3+3;
Insert into stu.result(res_id,stu_id,eng,maths,science) values (stu.seq_no.NEXTVAL,Lcntr,v_number1,v_number2,v_number3);
END LOOP;
end;
But my table is loaded as:(please ignore first two row data,i inserted it manually):
The data for eng,maths,science is not being inserted.why it is happening so?
That's because your variables are NULL. NULL + 1 = NULL as well.
If you modify declaration to
v_number1 number := 0;
v_number2 number := 0;
v_number3 number := 0;
something might happen.

Associative array issue

I have created an associative array, I understand it can be used different way of writing but however just need tips how to make this work. Currently when I compile this block I would receive no data found. Thank you!
DECLARE
TYPE type_state IS TABLE OF VARCHAR(50)
INDEX BY VARCHAR2(50);
tbl_state type_state;
lv_statecity1_txt VARCHAR2(30):= 'TAMPA';
lv_statecity2_txt VARCHAR2(30):= 'ATLANTA';
lv_statecity3_txt VARCHAR2(30):= 'NYC';
lv_cnt_num NUMBER(5) := 0;
BEGIN
tbl_state('FLORIDA') := lv_statecity1_txt;
tbl_state('GEORGIA') := lv_statecity2_txt;
tbl_state('New_York') := lv_statecity3_txt;
FOR i IN 1..tbl_state.count loop
IF tbl_state(i) IS NOT NULL THEN
LV_CNT_NUM := LV_CNT_NUM + 1;
dbms_output.put_line(tbl_state(i));
END IF;
END LOOP;
dbms_output.put_line('That''s it folks');
END;
tbl_state is a table of strings indexed by strings - passing in index values 1, 2, 3 (numbers) won't work.
It is true that array pairs are still ordered (first, second etc.), but accessing them in a loop is a bit more complicated. You will need a WHILE loop, and the index (I kept the name i to match your code as closely as possible) must be declared to be the same data type and length as the keys in the array.
DECLARE
TYPE type_state IS TABLE OF VARCHAR(50)
INDEX BY VARCHAR2(50);
tbl_state type_state;
lv_statecity1_txt VARCHAR2(30):= 'TAMPA';
lv_statecity2_txt VARCHAR2(30):= 'ATLANTA';
lv_statecity3_txt VARCHAR2(30):= 'NYC';
lv_cnt_num NUMBER(5) := 0; -- WHAT IS THIS FOR? NEEDED??
i varchar2(50); -- Notice this line
BEGIN
tbl_state('FLORIDA') := lv_statecity1_txt;
tbl_state('GEORGIA') := lv_statecity2_txt;
tbl_state('New_York') := lv_statecity3_txt;
i := tbl_state.first; -- And this line
while (i is not null) loop -- And this one
LV_CNT_NUM := LV_CNT_NUM + 1;
dbms_output.put_line(tbl_state(i));
i := tbl_state.next(i); -- And this one
END LOOP;
dbms_output.put_line('That''s it folks');
END;
/

Oracle - How to handle 32K+ string length in variables

I am using oracle 11g. Whenever I encountered strings larger than varchar2 size limit, In sql server I use to split the data into multiple variables as below and then join them while execution. However Oracle seems to be expecting 32K combined size before execution. I am getting "ORA-20000: ORU-10028: line length overflow, limit of 32767 bytes per line" error.
I am using these variables in an oralce script (not stored procs). Last 2 statements are throwing the above error and individually I am able to show the value.
Thanks in advance.
DECLARE
sViewQuery varchar2(32000);
sViewSelectQuery varchar2(32000);
BEGIN
---Assign values of 32,000 letter string (dynamic query)
sViewSelectQuery:='32K string...';
sViewQuery:='32K string..';
DBMS_OUTPUT.PUT_LINE(sViewQuery||sViewSelectQuery);
EXECUTE IMMEDIATE sViewQuery||sViewSelectQuery;
END;
You can use DBMS_SQL Package for this:
DECLARE
stmt DBMS_SQL.VARCHAR2A;
c number;
res number;
BEGIN
stmt(1) := 'create view view_a (';
stmt(2) := 'col_a, ';
stmt(3) := 'col_b, ';
stmt(4) := 'col_c) as '
stmt(5) := 'select ';
stmt(6) := 'col_bb, ';
stmt(7) := 'col_cc + col_ee + DECODE(...), ';
stmt(8) := 'col_dd) ';
stmt(9) := 'from table_b ';
stmt(10) := 'where ... ';
-- each element can have up to 32K characters, number of elements is (almost) unlimited
c := DBMS_SQL.open_cursor;
DBMS_SQL.parse(c, stmt, 1,10, TRUE, DBMS_SQL.NATIVE);
res := DBMS_SQL.execute(c);
DBMS_SQL.close_cursor(c);
END;
You should use a CLOB, Character Large OBject. You can handle 32K+ string length, since CLOB can contain up to 4GB of data.
For more info: http://docs.oracle.com/javadb/10.3.3.0/ref/rrefclob.html

Resources