Да, наконец, есть :) Стандарт SQL 2016 определяет Полиморфные функции таблицы
SQL: 2016 вводит полиморфные табличные функции (PTF), которым не нужно задавать тип результата заранее. Вместо этого они могут предоставить процедуру описания компонента, которая определяет тип возвращаемого значения во время выполнения. Ни автору PTF, ни пользователю PTF не нужно заранее объявлять возвращаемые столбцы.
PTF, как описано в SQL: 2016, еще не доступны ни в одной из протестированных баз данных.10 Заинтересованные читатели могут обратиться к бесплатному техническому отчету «Полиморфные табличные функции в SQL», выпущенному ISO. Ниже приведены некоторые примеры, обсуждаемые в отчете:
CSVreader, который считывает строку заголовка файла CVS, чтобы определить количество и имена возвращаемых столбцов
Pivot (фактически unpivot), который превращает группы столбцов в строки (пример: phonetype, phonenumber) - me: нет более жестко закодированных строк:)
TopNplus, который проходит через N строк на раздел и одну дополнительную строку с итогами оставшихся строк
Oracle 18c
реализует этот механизм. 18c Пример полиморфной табличной функции Skip_col Oracle Live SQL и Пример полиморфной табличной функции Skip_col
В этом примере показано, как пропустить данные на основе имени / конкретного типа данных:
CREATE PACKAGE skip_col_pkg AS
-- OVERLOAD 1: Skip by name
FUNCTION skip_col(tab TABLE, col columns)
RETURN TABLE PIPELINED ROW POLYMORPHIC USING skip_col_pkg;
FUNCTION describe(tab IN OUT dbms_tf.table_t,
col dbms_tf.columns_t)
RETURN dbms_tf.describe_t;
-- OVERLOAD 2: Skip by type --
FUNCTION skip_col(tab TABLE,
type_name VARCHAR2,
flip VARCHAR2 DEFAULT 'False')
RETURN TABLE PIPELINED ROW POLYMORPHIC USING skip_col_pkg;
FUNCTION describe(tab IN OUT dbms_tf.table_t,
type_name VARCHAR2,
flip VARCHAR2 DEFAULT 'False')
RETURN dbms_tf.describe_t;
END skip_col_pkg;
и тело:
CREATE PACKAGE BODY skip_col_pkg AS
/* OVERLOAD 1: Skip by name
* NAME: skip_col_pkg.skip_col
* ALIAS: skip_col_by_name
*
* PARAMETERS:
* tab - The input table
* col - The name of the columns to drop from the output
*
* DESCRIPTION:
* This PTF removes all the input columns listed in col from the output
* of the PTF.
*/
FUNCTION describe(tab IN OUT dbms_tf.table_t,
col dbms_tf.columns_t)
RETURN dbms_tf.describe_t
AS
new_cols dbms_tf.columns_new_t;
col_id PLS_INTEGER := 1;
BEGIN
FOR i IN 1 .. tab.column.count() LOOP
FOR j IN 1 .. col.count() LOOP
tab.column(i).pass_through := tab.column(i).description.name != col(j);
EXIT WHEN NOT tab.column(i).pass_through;
END LOOP;
END LOOP;
RETURN NULL;
END;
/* OVERLOAD 2: Skip by type
* NAME: skip_col_pkg.skip_col
* ALIAS: skip_col_by_type
*
* PARAMETERS:
* tab - Input table
* type_name - A string representing the type of columns to skip
* flip - 'False' [default] => Match columns with given type_name
* otherwise => Ignore columns with given type_name
*
* DESCRIPTION:
* This PTF removes the given type of columns from the given table.
*/
FUNCTION describe(tab IN OUT dbms_tf.table_t,
type_name VARCHAR2,
flip VARCHAR2 DEFAULT 'False')
RETURN dbms_tf.describe_t
AS
typ CONSTANT VARCHAR2(1024) := upper(trim(type_name));
BEGIN
FOR i IN 1 .. tab.column.count() LOOP
tab.column(i).pass_through :=
CASE upper(substr(flip,1,1))
WHEN 'F' THEN dbms_tf.column_type_name(tab.column(i).description)
!=typ
ELSE dbms_tf.column_type_name(tab.column(i).description)
=typ
END /* case */;
END LOOP;
RETURN NULL;
END;
END skip_col_pkg;
и пример использования:
-- skip number cols
SELECT * FROM skip_col_pkg.skip_col(scott.dept, 'number');
-- only number cols
SELECT * FROM skip_col_pkg.skip_col(scott.dept, 'number', flip => 'True')
-- skip defined columns
SELECT *
FROM skip_col_pkg.skip_col(scott.emp, columns(comm, hiredate, mgr))
WHERE deptno = 20;
Я настоятельно рекомендую прочитать весь пример (создание автономных функций вместо вызовов пакетов).
Вы можете легко перегрузить метод пропуска, например: пропустить столбцы, которые не начинаются / заканчиваются определенным префиксом / суффиксом.
db <> демо fidde