PL SQL如何使用变量处理记录字段

时间:2016-03-04 09:58:37

标签: oracle plsql oracle10g

是否可以使用变量从记录字段获取值来对其进行处理?如果是,我该怎么办?

当我这样做的时候它会起作用。

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;

但是当我这样改变时:

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;

我收到错误:

 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"

3 个答案:

答案 0 :(得分:1)

根据AskTom,您需要将记录存储在一个包中:

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;
/

答案 1 :(得分:1)

您可以在XMLtype中翻译您的请求。然后使用XmlType

例如:

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;

答案 2 :(得分:0)

您无法使用变量名称直接引用记录字段。您可以使用the dbms_sql package执行此操作,但这似乎有点过分了:

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;
/

如果你知道列总是一个数字,你可以为l_value使用更具体的数据类型。或者,您可以拥有每种可能类型的变量,并根据数据类型选择要使用的变量,您可以从l_desc(i)获取该数据类型。

但假设你知道表结构,你可以改为改变值:

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;
/