5

別のプロシージャの IN 句で使用できる関数またはプロシージャを記述したいと考えています。関数またはプロシージャは ID 番号を返します。

主な手順は次のようになります

SELECT *
FROM EMPLOYEES
WHERE OFFICE_ID IN (GET_OFFICE_IDS);  -- GET_OFFICE_IDS requires no parameters

GET_OFFICE_IDS は、コンマで区切られた ID を持つ VARCHAR2 を返します。メイン プロシージャを実行すると、意味のある "ORA-01722: 無効な番号" エラーが表示されますが、ここからどこに行く必要があるのか​​ わかりません。

メイン プロシージャが使用する一時テーブルを作成するには、GET_OFFICE_IDS が必要ですか? もしそうなら、パフォーマンスのペナルティはありますか?

4

5 に答える 5

6

EMP テーブルを使用した、ネストされたテーブル ソリューションの実例を次に示します。

create type t_ids is table of integer
/

create or replace function get_office_ids return t_ids
is
   l_ids t_ids := t_ids();
   l_idx integer := 0;
begin
   for r in (select empno from emp where deptno=10)
   loop
      l_ids.extend;
      l_idx := l_idx+1;
      l_ids(l_idx) := r.empno;
   end loop;
   return l_ids;
end;
/

select ename from emp where empno in (select * from table(get_office_ids));


ENAME
----------
CLARK
KING
TEST
MILLER
BINNSY
FARMER
于 2009-02-18T17:09:01.783 に答える
3

単純な力ずくのアプローチ:

WHERE ','||GET_OFFICE_IDS||',' LIKE '%,'||OFFICE_ID||',%'

入れ子になったテーブルを返すように GET_OFFICE_IDS を変更し、次のようなものを使用することをお勧めします。

OFFICE_ID IN (SELECT * FROM TABLE(GET_OFFICE_IDS))
于 2009-02-18T16:38:25.320 に答える
2

私はオラクル SQL を使用していませんが、ID を返すために別の select ステートメントを IN 句に単純に入れることはできませんか?

SELECT * FROM EMPLOYEES WHERE OFFICE_ID IN (SELECT ID FROM tbl_X WHERE x=y);

...それとも、もう少し複雑なことをしたいと思っていましたか?

于 2009-02-18T16:37:09.347 に答える
1

編集:私はSOの基本的なルールを破りました.OPには答えませんでした. すでに受け入れられている回答があるので、警告するのが賢明だと感じました。

原則として、SQL と PL/SQL を混在させることは非常に悪い考えです。コード用に 2 つの別個のエンジンがあります。SQL エンジンと PL/SQL エンジンがあります。何千ものスイッチを前後に強制すると、パフォーマンスが完全に失われます。

プログラマーがこれをやりたい理由を理解しています。わかった。それはすべてカプセル化されていて、暖かくてぼやけていますが、あなたをひどく苦しめます. 自然と同じように、景色と音であなたを誘惑し、足首を骨折します。

こんな馬鹿げたことでも。

create or replace function my_Date (p_Date in date)
return varchar
as
begin

    return to_char(p_Date, 'yyyy/mm/dd');

end;

あなたの実行時間を殺します。

自動トレースをオンにする

次に、これらを実行します。

select to_char(created, 'yyyy/mm/dd'), to_char(last_ddl_time, 'yyyy/mm/dd')  from all_objects


select my_date(created), my_Date(last_DDL_TIME) From all_objects

2 番目のものは、実行に 2 倍の時間がかかります。1 秒で 1 秒、2 秒で 2 クエリの答えが得られます。

そして、これは非常に単純なケースです...私がしているのは、値をキャストすることだけです。好きなように参加しなければならない場合を想像してみてください。本当に最悪のケースです。

関数内で何かを非表示にした場合、オプティマイザが完全に実行できないことを考えてみてください。

IN を実行する場合、結合として実行する方がはるかに高速な場合があります。特定の条件が真の場合、オプティマイザーがそれを行います。IN を JOIN に変換します。しかし、関数内で select を偽装しているため、条件が熟しているかどうかを判断できなくなります。オプティマイザーに次善のことを強制しました。

オプティマイザが依存する重要な統計の 1 つは行数です。1行ですか、それとも10億ですか。テーブルとインデックスの統計からわかります。関数に関する統計はありません。

それらをそこに置くことができます。カーディナリティをほのめかすことができます。できないと言っているわけではありませんが、なぜですか? なぜあなたはしたいですか?あなたがこの関数を使用しているのは、あなたが勤勉なプログラマーであり、冗長なコードを関数に分解するように一生言われてきたからに見えます。

頭の中にあるこれらのルールは、SQL にはほとんど適用されません。オプティマイザはコンパイラではありません。関数をインライン化することはできません。オプティマイザが最適な計画を立てるのを支援できるのは、あなただけです。

于 2009-02-18T20:17:04.683 に答える