Oracle中如何根据列名select列

How to select columns on the basis of column names in Oracle

我尝试了以下方法,但不起作用。

select (
    select COLUMN_NAME from ALL_TAB_COLUMNS 
    WHERE COLUMN_NAME LIKE '%_<SOME_SUFFIX>' 
    AND OWNER = '<SCHEMA>' AND TABLE_NAME = '<TABLE_NAME>'
)
FROM <SCHEMA>.<TABLE_NAME>

在这个例子中,我正在编写一个 select 语句,该语句基于名称满足特定条件的 table(作为参数传递给函数)中的列列表。因为它是 Scott 的 emp table 并且它的列没有任何后缀,所以我选择名称包含字母 E.

的列

基于该列列表(与 listagg 聚合),l_str 变量包含一个 full select 语句,它是 - 在turn - 一个 source for refcursor.

SQL> CREATE OR REPLACE FUNCTION f_test (par_table_name IN VARCHAR2)
  2     RETURN SYS_REFCURSOR
  3  IS
  4     l_cols  VARCHAR2 (100);
  5     l_str   VARCHAR2 (200);
  6     rc      SYS_REFCURSOR;
  7  BEGIN
  8     -- list of column names that satisfy some condition; for example, have some suffix or, as
  9     -- in my example, have a letter "E" in their name
 10     SELECT LISTAGG (column_name, ', ') WITHIN GROUP (ORDER BY column_name)
 11       INTO l_cols
 12       FROM user_tab_columns
 13      WHERE     table_name = DBMS_ASSERT.sql_object_name (par_table_name)
 14            AND INSTR (column_name, 'E') > 0;
 15
 16     l_str :=
 17           'select '
 18        || l_cols
 19        || ' from '
 20        || DBMS_ASSERT.sql_object_name (par_table_name);
 21
 22     OPEN rc FOR l_str;
 23
 24     RETURN rc;
 25  END;
 26  /

Function created.

测试:

SQL> select f_test('EMP') from dual;

F_TEST('EMP')
--------------------
CURSOR STATEMENT : 1

CURSOR STATEMENT : 1

    DEPTNO      EMPNO ENAME      HIREDATE
---------- ---------- ---------- ----------
        20       7369 SMITH      17/12/1980
        30       7499 ALLEN      20/02/1981
        30       7521 WARD       22/02/1981
        20       7566 JONES      02/04/1981
        30       7654 MARTIN     28/09/1981
        30       7698 BLAKE      01/05/1981
        10       7782 CLARK      09/06/1981
        20       7788 SCOTT      09/12/1982
        10       7839 KING       17/11/1981
        30       7844 TURNER     08/09/1981
        20       7876 ADAMS      12/01/1983
        30       7900 JAMES      03/12/1981
        20       7902 FORD       03/12/1981
        10       7934 MILLER     23/01/1982

14 rows selected.

    
SQL> select f_test('DEPT') from dual;

F_TEST('DEPT')
--------------------
CURSOR STATEMENT : 1

CURSOR STATEMENT : 1

    DEPTNO DNAME
---------- --------------
        10 ACCOUNTING
        20 RESEARCH
        30 SALES
        40 OPERATIONS


SQL>