【问题标题】:Oracle cusor return result and get value by dynamic column nameOracle 游标返回结果并通过动态列名取值
【发布时间】:2015-11-13 00:55:21
【问题描述】:

作为标题,我想通过列名获取值作为游标结果中的参数。

找了半天也没找到答案,有大神帮忙吗?

--common usage
BEGIN
    for rowValue in (select code, name from tableA)
    LOOP
     -- rowValue.code  rowValue.name
    END LOOP;
END


BEGIN
    FOR rowValue IN (select * from tableA)
    LOOP
        -- tableB will keep some column's names about talbeA
        FOR columnNames IN (select name from tableB)
        LOOP
         -- want to use like:  rowValue.(columnNames.name)
        END LOOP;
    END LOOP;
END

【问题讨论】:

  • 这听起来是个糟糕的主意。想要这样做的原因是什么?
  • 您可以使用动态 SQL 来实现 - 请参阅 dbms_sql - 但它不会很漂亮,而且听起来确实是个糟糕的主意。

标签: oracle plsql for-in-loop


【解决方案1】:

您可以像这样使用 DBMS_SQL:

DECLARE
  l_cursor                INTEGER;
  l_column_count          INTEGER;
  l_column_descriptions   SYS.DBMS_SQL.desc_tab;
  l_column_value          VARCHAR2 (4000);
  l_status                INTEGER;

  TYPE col_map_tab_type IS TABLE OF INTEGER
    INDEX BY VARCHAR2 (30);

  col_map_tab             col_map_tab_type;
BEGIN
  l_cursor   := sys.DBMS_SQL.open_cursor;

  -- parse SQL
  sys.DBMS_SQL.parse (c => l_cursor, statement => 'SELECT * FROM DBA_OBJECTS WHERE ROWNUM <= 10', language_flag => sys.DBMS_SQL.native);

  -- Describe columns
  sys.DBMS_SQL.describe_columns (c => l_cursor, col_cnt => l_column_count, desc_t => l_column_descriptions);

  FOR i IN 1 .. l_column_count LOOP
    col_map_tab (l_column_descriptions (i).col_name)   := i;
    DBMS_SQL.define_column (l_cursor,
                            i,
                            l_column_value,
                            4000);
  END LOOP;

  l_status   := sys.DBMS_SQL.execute (l_cursor);

  WHILE (sys.DBMS_SQL.fetch_rows (l_cursor) > 0) LOOP
    FOR column_names IN (SELECT column_name
                         FROM   dba_tab_columns
                         WHERE  table_name = 'DBA_OBJECTS'
                         AND    column_name LIKE 'O%') LOOP
      DBMS_SQL.COLUMN_VALUE (l_cursor, col_map_tab (column_names.column_name), l_column_value);
      DBMS_OUTPUT.put_line (column_names.column_name || ' = ' || l_column_value);
    END LOOP;
  END LOOP;

  sys.DBMS_SQL.close_cursor (l_cursor);
END;

【讨论】:

  • 您可以使用另一个col_map_tab 来存储目标列名,而不是使用FOR column_names IN ... 重新查询您从主查询中获取的每一行。 (在这个演示中,第一个引用 DBA_OBJECTS` 是 OP 的表 A,第二个是表 B,对吧?)
  • 是的,我只是担心 DBMS_SQL 使用动态 SQL 的性能低下,(TableA 有超过 20 万行)。我会测试它。
  • @AlexPoole 是的——但我想让示例的结构在某种程度上接近 OP 的初始代码。实际上,不是第二个col_map_tab,我可能只是循环遍历我拥有的那个并删除表 B 中没有的任何内容(在我的示例中为 DBA_TAB_COLUMNS)。然后,只需迭代 col_map_tab 作为内部循环。
猜你喜欢
  • 1970-01-01
  • 2011-01-10
  • 1970-01-01
  • 2012-05-15
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-03-20
  • 1970-01-01
相关资源
最近更新 更多