Reputation: 11
Is it possible to get value from record field using variable to adress it? If yes how can i do it?
When i do it like this it works.
DECLARE
dev_day JX_DATA_20160301%ROWTYPE;
ichar varchar2(3);
BEGIN
SELECT * into dev_day FROM JX_DATA_20160301 WHERE did=100;
ichar:='H01';
dbms_output.put_line(dev_day.H01);
END;
But when i change it this way:
DECLARE
dev_day JX_DATA_20160301%ROWTYPE;
ichar varchar2(3);
BEGIN
SELECT * into dev_day FROM JX_DATA_20160301 WHERE did=100;
ichar:='H01';
dbms_output.put_line(dev_day.ichar);
END;
I get error:
ORA-06550: linia 7, kolumna 32: PLS-00302: component
'ICHAR' must be declared ORA-06550: linia 7, kolumna 3: PL/SQL:
Statement ignored
06550. 00000 - "line %s, column %s:\n%s"
Upvotes: 1
Views: 113
Reputation: 3186
You can translate your request in XMLtype
. And then work with XmlType
.
For example:
DECLARE
-- Local variables here
xml_t xmltype;
ichar CHAR(3) := 'H01';
l_refcursor SYS_REFCURSOR;
BEGIN
OPEN l_refcursor FOR
SELECT * FROM JX_DATA_20160301 WHERE did=100;
xml_t := XMLTYPE(l_refcursor);
dbms_output.put_line(xml_t.extract('//'||ichar||'/text()').getStringVal);
END;
Upvotes: 1
Reputation: 191520
You can't directly refer to the record field using a variable name . You could do this using the dbms_sql
package, but it seems like overkill:
DECLARE
l_column_name user_tab_columns.column_name%type;
l_cursor integer;
l_cols integer;
l_rows integer;
l_desc dbms_sql.desc_tab;
l_value varchar2(4000);
BEGIN
l_column_name := 'H01';
l_cursor := dbms_sql.open_cursor;
dbms_sql.parse(l_cursor, 'SELECT * FROM JX_DATA_20160301 WHERE did=:did',
dbms_sql.native);
dbms_sql.bind_variable(l_cursor, 'did', 100);
l_rows := dbms_sql.execute(l_cursor);
dbms_sql.describe_columns(c => l_cursor, col_cnt => l_cols,
desc_t => l_desc);
for i in 1..l_cols loop
dbms_sql.define_column(l_cursor, i, l_value, 4000);
end loop;
while dbms_sql.fetch_rows(l_cursor) > 0 loop
for i in 1..l_cols loop
if l_desc(i).col_name = l_column_name then
dbms_sql.column_value(l_cursor, i, l_value);
dbms_output.put_line(l_value);
end if;
end loop;
end loop;
dbms_sql.close_cursor(l_cursor);
END;
/
You can use a more specific data type for l_value
if you know the column will always be a number, say. Or you can have a variable of each possible type and choose which to use based on the data type, which you can get from l_desc(i)
.
But assuming you know the table structure, you could switch on the variable value instead:
DECLARE
dev_day JX_DATA_20160301%ROWTYPE;
ichar varchar2(3);
BEGIN
SELECT * into dev_day FROM JX_DATA_20160301 WHERE did=100;
ichar:='H01';
case ichar
when 'H01' then
dbms_output.put_line(dev_day.h01);
when 'H02' then
dbms_output.put_line(dev_day.h02);
-- ... etc, for each column you might want
end case;
END;
/
Upvotes: 0
Reputation: 168520
According to AskTom, you need to store the record in a package:
CREATE PACKAGE temp_storage_pkg
AS
JX_DATA_REC JX_DATA_20160301%ROWTYPE;
END;
/
DECLARE
ichar CHAR(3) := 'H01';
value VARCHAR2(4000);
BEGIN
SELECT * INTO temp_storage_pkg.JX_DATA_REC FROM JX_DATA_20160301 WHERE did=100;
EXECUTE IMMEDIATE 'BEGIN :x := temp_storage_pkg.JX_DATA_REC.' || ichar || '; END;'
USING OUT value;
DBMS_OUTPUT.PUT_LINE( value );
END;
/
Upvotes: 1