それぞれのテーブルの構造が似ているとします(つまり、すべてのテーブルにrep、mgr、mgr2、mgr3、mgr4などの列があります)。それらの列がすべて存在する場合は動的にチェックし、真または偽の条件を返す関数を作成できます。
次の関数は、PERSON_LOGGED_IN(回答の目的では整数のキー値と見なされます)と、検索するテーブルのスキーマと名前(スキーマ名が含まれています異なるスキーマの重複するテーブル名は競合しません)。
次に、条件のセット(rep、mgr、mgr2など)に一致する、指定したテーブルのすべての列のリストを取得します。これは、異なる表に異なる列がある場合は、がである可能性があるすべてを指定でき、表に実際に存在する列のみが照合されることになります。
一致する列が特定されたら、一致する行の数を確認して1または0を戻します。プレーンSQLはPL/SQLのようなブール値を認識しないため数値を返します。
最終的なクエリはなる:
SELECT *
FROM BOATS
WHERE IN_HIERARCHY(PERSON_LOGGED_IN, 'SCHEMA.BOATS') = 1
そして、ここでの機能です:
CREATE OR REPLACE FUNCTION IN_HIERARCHY (
PERSON_LOGGED_IN IN PLS_INTEGER,
TABLE_SCHEMA_AND_NAME IN VARCHAR2
) RETURN PLS_INTEGER
IS
MATCHING_COLUMNS VARCHAR2(200);
NUMBER_OF_ROWS_FOUND PLS_INTEGER := 0;
BEGIN
select LISTAGG(COLUMN_NAME, ',') WITHIN GROUP (ORDER BY COLUMN_NAME)
INTO MATCHING_COLUMNS
from all_tab_columns
where OWNER = regexp_substr(TABLE_SCHEMA_AND_NAME,'[^.]+', 1, 1)
AND TABLE_NAME = regexp_substr(TABLE_SCHEMA_AND_NAME,'[^.]+', 1, 2)
and COLUMN_NAME in ('REP', 'MGR', 'MGR2', 'MGR3', 'MGR4');
EXECUTE IMMEDIATE
'SELECT COUNT(*)
FROM ' || TABLE_SCHEMA_AND_NAME || '
WHERE :PERSON_LOGGED_IN IN (' || MATCHING_COLUMNS || ')'
INTO NUMBER_OF_ROWS_FOUND
USING PERSON_LOGGED_IN;
IF NUMBER_OF_ROWS_FOUND > 0 THEN
RETURN 1;
ELSE
RETURN 0;
END IF;
END;
/
サイドノート:私は個人的にテーブルのリストを取得する方法を知りません。 from
句を実行しているステートメントに基づいてこの関数内から削除することができますが、何らかの方法でそれを判断できる場合は、論理的にも関数からテーブル名の引数を削除することもできます。しかし、それはおそらくそれほど価値がなく、実際のwhere
節はおそらく読者にとってあまり明確ではないでしょう。
@kordirkoが指摘するようにクエリを簡素化し、それをより読みやすくで本当にただ興味があるならその後、再び、、、その後、このような何かがずっと簡単になります:
SELECT *
FROM BOATS
WHERE PERSON_LOGGED_IN IN (REP, MGR, MGR2, MGR3, MGR4)
ため息..別の設計が間違っているテーブル構造。それを変更する可能性はありますか?理論的には、ただ1つのREP列が必要です。従業員/マネージャ階層は他の場所に格納する必要があります。担当者が新しいマネージャーを取得するとどうなりますか?または、スタッフの変更が一般的です - これらのテーブルを新しい従業員に更新する必要がありますか? –
これはやや工夫された例ですが、貧弱なデザインに対するあなたのコメントと関連して、これには過去のデータが含まれているという理由があります。このアプリケーションは、販売時点の担当者の階層を知る必要があります。それが外部で管理されている場合(別の表でも言えば)、すべての担当者とすべての階層を何年も保持する必要があります。 – user1009073
これは優れていますが、残念ながら、製品タイプを持つ1つのテーブルではなく、各製品のテーブルがあります。私はあなたが6つのパラメータ( 'Person_logged_in'と従業員レベルの5つ)を取る関数を書くことができると思うので、あなたのクエリは' select * from boats 'になるかもしれないと思いますin_hiearchy(person_logged_in、rep、mgr、mgr2、mgr3 、mgr4)= 1' –