この質問は、コードとコーディング標準の効率を改善するためのPLSQLに関するものです。
ヘルプ、ポインタ、リファレンス、提案は大歓迎です。
質問:
i_flag
タイプがのINPUTパラメータを持つplsqlプロシージャがありますBOOLEAN
。
このi_flagの値(trueまたはfalseのいずれか)に基づいて、SQLクエリを実行する必要があります。値がTRUE
SQL1(クエリ1.1と想定)の場合、値がFALSE
SQL2(クエリ1.2と想定)の場合は実行されます。
SQL2は、where句が追加されていることを除いて、SQL1と同じです。
SQL1(1.1)
select a.user_id, a.user_name, a.dept_id, b.country from user a , contact b
where a.user_id = b.user_id;
SQL1(1.2)
select a.user_id, a.user_name, a.dept_id, b.country from user a , contact b
where a.user_id = b.user_id
and a.user_status is not null;
plsqlでIF-ELSEを記述する代わりに、このクエリを単一のSQLクエリで記述することは可能ですか?sqlオラクル選択するplsqlplsqldeveloperシェアフォローする2015年9月25日18:46に編集ムレイニク246k4545ゴールドバッジ228228個のシルバーバッジ270270個のブロンズバッジ2015年9月25日17:12に 尋ねたディーパン1171ゴールドバッジ1個1シルバーバッジ1個7ブロンズバッジ7個
- 2
which can be either true or false
はい、それは通常ブール値のしくみです;) – Juan Carlos Oropeza 2015 年9月25日17:44 - 1もちろん、@ JuanCarlosOropezaもnullになる可能性があります。それは…醜態ことだろうが – デヴィッド・オルドリッジ 9月27日’15 9時41分で
i_flag
最も自己文書化されたパラメータ名のようには聞こえません。 – ウィリアムロバートソン 2015年11月11日16:56
5つの答え
論理or
演算子を使用して、1つのクエリで同じ動作を作成できます。
select a.user_id, a.user_name, a.dept_id, b.country
from user a , contact b
where a.user_id = b.user_id AND (i_flag = TRUE OR a.user_status IS NOT NULL)
ちなみに、暗黙的な結合(from
句に2つのテーブルがある)は非推奨の構文であり、最新の明示的な構文に切り替えることをお勧めします。
SELECT a.user_id, a.user_name, a.dept_id, b.country
FROM user a
JOIN contact b ON a.user_id = b.user_id
where i_flag = TRUE OR a.user_status IS NOT NULL
シェアフォローする2015年9月25日18:46に編集2015年9月25日17:19に 回答ムレイニク246k4545ゴールドバッジ228228個のシルバーバッジ270270個のブロンズバッジ
- 6
boolean
は有効なSQLデータ型ではないため、これは機能しません。PL / SQLでのみ有効です。ブールパラメータを、varchar2(1)
YまたはNなどのSQL型であるローカル変数に変換する必要があります。その後、そのローカル変数をクエリで使用できます。 – ジャスティン洞窟 2015年9月25日18:49
まず、SQLクエリでブールパラメータを使用する場合は、NUMBERなどのSQL互換タイプに置き換える必要があります。つまり、FALSEまたはTRUEの代わりに0または1を使用します。
第2に、ORに基づくMureinikの回答は機能しますが、代替手段を使用すると、Oracleの方がパフォーマンスが向上することがよくあります。1つの選択肢は次のようなものです。
SELECT a.user_id, a.user_name, a.dept_id, b.country
FROM user a
JOIN contact b ON a.user_id = b.user_id
WHERE 1 = CASE WHEN i_flag = 1 THEN 1
WHEN a.user_status IS NOT NULL THEN 1
ELSE 0 END
それはきれいではありませんが、より大きなクエリでは時々非常に役立ちます。シェアフォローする2015年9月25日22:56に回答ポール・キエニッツ84955つのシルバーバッジ2222個のブロンズバッジコメントを追加0
構文的には、上記の答えはすべて素晴らしいです。しかし、私の2セントは、パフォーマンスに役立つ可能性のある別の変更について言及しています。PL / SQL procを実行する際の最大のボトルネックは、PL / SQLとSQLエンジン(ORACLEのアーキテクチャによって分離されている)の間でバウンスするときに見られます。したがって、経験則では、各プロシージャへの個々の呼び出しの量を最小限に抑えます。
このルールを質問に適用する場合は、クエリ対象のすべてのユーザーとその適切なブール値を含むrefcursorをプロシージャに渡すことが可能かどうかを確認する必要があります。プロシージャがユーザーのバッチのループ内から呼び出されるようになった場合、そうすることで、多数にスケーリングするときにパフォーマンスが大幅に向上します。シェアフォローする2015年9月26日9:47に回答ヤロン・イダン4,80644つのゴールドバッジ3232個のシルバーバッジ6060個のブロンズバッジコメントを追加0
このために動的SQLを作成するのは良い選択だと思います。
create or replace procedure sp_..(i_flag boolean)
as
sql_stmt varchar2(1000):='select a.user_id, a.user_name,'||
'a.dept_id,b.country from user a , contact b '||
'where a.user_id = b.user_id';
begin
if (i_flag=false) then
sql_stmt:=sql_stmt||' and a.user_status is not null';
end if;
---do some stuff with sql_stmt(i.e. refcursor)
end sp_..;
シェアフォローする2015年9月26日13:58に 回答ソムナスバンドパディヤイ464ブロンズバッジ4個
- 1動的SQLのIMOの無用な使用。YMMV。 – user272735 2015 年9月28日13:13
- dbms_sql @ user272735を使用しますか? – Somnath Bandopadhyay 2015 年9月28日13:29
- @Mureinikが受け入れた回答は(正しい)解決策であるため、これ以上の例を提供する必要はありません。静的SQLで同じ機能を作成できる場合、動的SQLは常に最適ではありません。 – user272735 2015 年9月30日5:15
- SQLエンジンはSQL以外の引数を解析しないため、入力パラメーター(i_flag = true)を試してみたことがあると思います。 – Somnath Bandopadhyay 2015年 10月1日9:52
- @Justin Caveはすでに言っています…私はそれを逃しました…静的SQLはそれを行うことができないので、dbms_sqlに依存する必要があります – Somnath Bandopadhyay 2015年 10月1日9:54
単一のクエリ内にor条件を実装できたとしても、パフォーマンスの観点からはあまり良い考えではない可能性があり、動的SQLの方が適している可能性があります。コードの効率を改善したい場合は、https://www.youtube.com/watch?v = rWEqO-GpJ4Mのように見てください。シェアフォローする2015年10月14日13:36に 回答clq1809ブロンズバッジ9個コメントを追加