はい、ついにあります:) SQL標準2016は多態的なテーブル関数を定義します
SQL:2016 では、結果の型を事前に指定する必要のない多相テーブル関数 (PTF) が導入されています。代わりに、実行時に戻り値の型を決定する記述コンポーネント プロシージャを提供できます。PTF の作成者も PTF のユーザーも、返される列を事前に宣言する必要はありません。
SQL:2016 で説明されている PTF は、テスト済みのデータベースではまだ利用できません。以下は、レポートで説明されている例の一部です。
CVS ファイルのヘッダー行を読み取って、返される列の数と名前を判別する CSVreader
列グループを行に変換するピボット (実際にはアンピボット) (例: phonetype、phonenumber) -- 私: ハードコーディングされた文字列はもう必要ありません :)
TopNplus: パーティションごとに N 行と、残りの行の合計を含む余分な 1 行を通過します。
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 デモ
関連: SQL クエリの列を動的に変更する方法 Chris Saxon 著