2016-05-27 10 views
0

プロシージャに引数 `EBN、BGE 'を渡しています。この引数をカーソルに渡します。カーソルを条件のある場所で使用する

create or replace procedure TEXT_MD (AS_IDS VARCHAR2) 
is 
CURSOR C_A (AS_ID VARCHAR2) IS 
     SELECT 
     name 
     FROM S_US 
     WHERE US_ID IN (AS_ID); 


BEGIN 


FOR A IN C_A (AS_IDS) LOOP 

DBMS_OUTPUT.PUT_LINE('I got here: '||AS_IDS); 

end loop; 


END; 

enter image description here

しかしカーソルの数をデバッグの一方ではまだnullです

enter image description here

だから私の質問は、なぜ条件で

+0

申し訳ありません。私は間違っています。 –

+0

@FrancescoSerra申し訳ありませんが、私はあなたを理解していません – Moudiz

+0

プロシージャに、コレクションではなくカンマを持つ単一の文字列を渡しています。 'us_id = 'EBN''または' us_id =' BGE''がある行ではなく、 'us_id = 'EBN、BGE''の行ではなく、コレクションを渡す必要がある行を見つけることが目標ですまたは入力パラメータを解析してコレクションにします。コレクションを受け入れるためにプロシージャのシグネチャを変更できますか(コールするアプリケーションはコレクション内を渡すことができますか)これは簡単なオプションです。 –

答えて

2

で値を返さないカーソルます文字列パラメータを渡しているので、文字列のリストではなく文字列として使用されます。ですから、カーソルは次のようなものになります

SELECT name 
FROM S_US 
WHERE US_ID IN ('EBN,BGE') 

これはもちろん、必要なことはしません。 プロシージャとパラメータを渡す方法を変更する必要がある場合があります。あなたは文字列パラメータを保持したい場合は、一つの方法は次のようになります。

セットアップ:

SQL> CREATE TABLE S_US 
    2 (
    3  US_ID, 
    4  NAME 
    5 ) AS 
    6  SELECT 'EBN', 'EBN name' FROM DUAL 
    7  UNION ALL 
    8  SELECT 'BGE', 'BGE name' FROM DUAL; 

Table created. 

手順:あなたは、文字列でそれを呼び出す必要があり

SQL> CREATE OR REPLACE PROCEDURE TEXT_MD_2(AS_IDS VARCHAR2) IS 
    2  vSQL varchar2(1000); 
    3  c sys_refcursor; 
    4  vName varchar2(16); 
    5 BEGIN 
    6  vSQL := 'SELECT name 
    7    FROM S_US 
    8    WHERE US_ID IN (' || AS_IDS || ')'; 
    9  open c for vSQL; 
10  loop 
11   fetch c into vName; 
12   if c%NOTFOUND then 
13    exit; 
14   end if; 
15   DBMS_OUTPUT.PUT_LINE(vName); 
16  END LOOP; 
17 END; 
18/

Procedure created. 

既にINのパラメータリストにフォーマットされています。

SQL> EXEC TEXT_MD_2('''EBN'',''BGE'''); 
EBN name 
BGE name 

PL/SQL procedure successfully completed. 

これは可能な方法の一例に過ぎず、これを行う方法ではありません。 この種のアプローチを使用する理由の1つとして、Justin Caveの言葉を考えてみてください。 "SQLインジェクションのためにセキュリティ上のリスクがあり、一定のハード解析による潜在的に大きなパフォーマンス上のペナルティがあります。

文字列を使って文字列を表現するのではなく、値リストを手続きに渡す方法をよく調べるべきだと思います。そうでインデックス化の有無、および、ストアドプロシージャ内かどうか、さまざまな方法でコレクションを定義することができ、ここでも

SQL> CREATE OR REPLACE TYPE tabVarchar2 AS TABLE OF VARCHAR2(16) 
    2/

Type created. 

SQL> 
SQL> CREATE OR REPLACE PROCEDURE TEXT_MD_3(AS_IDS tabVarchar2) IS 
    2  vSQL         VARCHAR2(1000); 
    3  c          SYS_REFCURSOR; 
    4  vName         VARCHAR2(16); 
    5 BEGIN 
    6  FOR i IN (SELECT name 
    7     FROM S_US INNER JOIN TABLE(AS_IDS) tab ON (tab.COLUMN_VALUE = US_ID)) 
    8  LOOP 
    9   DBMS_OUTPUT.PUT_LINE(i.name); 
10  END LOOP; 
11 END; 
12/

Procedure created. 

SQL> 
SQL> DECLARE 
    2  vList         tabVarchar2 := NEW tabVarchar2(); 
    3 BEGIN 
    4  vList.EXTEND(2); 
    5  vList(1) := 'BGE'; 
    6  vList(2) := 'EBN'; 
    7  TEXT_MD_3(vList); 
    8 END; 
    9/
BGE name 
EBN name 

PL/SQL procedure successfully completed. 

SQL> 

;:ここ は、コレクションと同じことを行うことが可能な方法でありますこれは可能な方法のうちの1つに過ぎず、環境やニーズに応じて、必ずしも最適ではありません。

+0

私はあなたの例を試しています – Moudiz

+0

最初の手順はうまくいかないでしょう。コレクションを使用しているバージョンがあります。プロシージャー内で動的SQLを使用した場合は、コンマ区切りのストリングを使用できますが、これはSQLインジェクションによるセキュリティー上のリスクであり、一定のハード解析のためにパフォーマンスに大きな影響を与える可能性があります。 –

+0

@JustinCave:私のエラー、私は動的SQLを持つものの代わりに間違った手順を投稿しました、ありがとう。ここで動的SQLを避けることについては、私はあなたの言葉をコピーしています。私はそれをより良く言うことができませんでした。再度、感謝します。 – Aleksej

関連する問題