2017-10-15 15 views
0

入力値を渡すのを手伝ってもらえますか(実行時には、一度に1つの変数に対して複数の値を入力することを意味します)。PLSQLの単一変数への入力として一度に複数の値を読み取る方法はありますか?

ここでは、ハードコードされた入力または1つの入力を同時に入力するコードを示します。

declare 
    type TEmpRec is record (
    EmployeeID EMPLOYEES.EMPLOYEE_ID%TYPE, 
    LastName EMPLOYEES.LAST_NAME%TYPE 
); 
    type TEmpList is table of TEmpRec; 
    vEmpList TEmpList; 
    --------- 
    function EmpRec(pEmployeeID EMPLOYEES.EMPLOYEE_ID%TYPE, 
        pLastName EMPLOYEES.LAST_NAME%TYPE default null) return TEmpRec is 
    -- Effective "Record constructor" 
    vResult TEmpRec; 
    begin 
    vResult.EmployeeID := pEmployeeID; 
    vResult.LastName := pLastName; 
    return vResult; 
    end; 
    --------- 
    procedure SearchRecs(pEmpList in out nocopy TEmpList) is -- Nocopy is a hint to pass by reference (pointer, so small) rather than value (actual contents, so big) 
    vIndex PLS_integer; 
    begin 
    if pEmpList is not null then 
     vIndex := pEmpList.First; 
     while vIndex is not null -- The "while" approach can be used on sparse collections (where items have been deleted) 
     loop 
     begin 
      select LAST_NAME 
      into pEmpList(vIndex).LastName 
      from EMPLOYEES 
      where EMPLOYEE_ID = pEmpList(vIndex).EmployeeID; 
     exception 
      when NO_DATA_FOUND then 
      pEmpList(vIndex).LastName := 'F'||pEmpList(vIndex).EmployeeID; 
     end; 
     vIndex := pEmpList.Next(vIndex); 
     end loop; 
    end if; 
    end; 
    --------- 
    procedure OutputRecs(pEmpList TEmpList) is 
    vIndex PLS_integer; 
    begin 
    if pEmpList is not null then 
     vIndex := pEmpList.First; 
     while vIndex is not null 
     loop 
     DBMS_OUTPUT.PUT_LINE ('pEmpList(' || vIndex ||') = '|| pEmpList(vIndex).EmployeeID||', '|| pEmpList(vIndex).LastName); 
     vIndex := pEmpList.Next(vIndex); 
     end loop; 
    end if; 
    end; 
begin 
    vEmpList := TEmpList(EmpRec(100), 
         EmpRec(34), 
         EmpRec(104), 
         EmpRec(110)); 
    SearchRecs(vEmpList); 
    OutputRecs(vEmpList); 
end; 
/

上記のプログラムは、入力値を1つずつ取ります。 しかし、私は以下のように試みたが、成功することができませんでした。

私は、入力をハードコーディングする代わりに(100,34,104,100)一度にコンソールからの入力を与えようとしました。 DECLAREセクションの

スニペット:DECLAREセクションの

BEGIN 
FOR j IN v_input.FIRST .. v_input.LAST LOOP 
    vEmpList := TEmpList(EmpRec(v_input(j).EmployeeID)); --to assign input values to vEmptList 

    SearchRecs(vEmpList); 
    OutputRecs(vEmpList); 
end loop; 
end; 
/

エラー: PLS-00306:間違った数またはタイプの最終BEGINセクションで

declare 
    type TEmpRec is record (
    EmployeeID EMPLOYEES.EMPLOYEE_ID%TYPE, 
    LastName EMPLOYEES.LAST_NAME%TYPE 
); 
    type TEmpList is table of TEmpRec; 
    v_input TEmpList := TEmpList(&v_input); -- to read multiple input at once 
    vEmpList TEmpList; 

'TEMPLIST'の呼び出しでの引数 LAST BEGIN seのエラーction: PLS-00320:この式の型の宣言は、一例として

不完全または不正な形式れる:時、iは同じ変数のための複数の入力値を読み取ることができが、私が通過することができませんこれは入力として、しかし、これを入力として私のメインプログラムにする方法を理解することができません。

DECLARE 
TYPE t IS TABLE OF VARCHAR2(100); 
ORDERS t := t(&ORDERS); 
BEGIN 
FOR j IN ORDERS.FIRST .. ORDERS.LAST LOOP 
dbms_output.put_line(ORDERS(j)); 
END LOOP; 
END; 
/

出力: PL/SQLプロシージャが正常に完了しました。 はオーダーの値を入力します:321153678

はありがとうございました。

+0

'TEmpRec'はプレーンなPL/SQLレコードタイプなので、コンストラクタはありません。コンストラクタが必要な場合は、オブジェクト型を作成する必要があります。より詳細な回答が必要な場合は、[mcve](https://stackoverflow.com/help/mcve)を使用すると問題がより明確になります。 –

答えて

0

recordのコレクションがあるため、employee_idsと従業員last_namesを別々に渡す必要があります。どのようにあなたは一回のショットでそれらを渡す予定ですか? ここには、3つのコレクション要素に対して2つの入力を使用して何かを実現するサンプルスクリプトがあります。

まず、TYPEPIPELINED functionのコレクションを作成し、カンマ区切りの値をCollections-に変換します。

CREATE TYPE test_type AS TABLE OF VARCHAR2(100); 


CREATE OR REPLACE FUNCTION f_convert2(p_list IN VARCHAR2) 
    RETURN test_type 
PIPELINED 
AS 
    l_string  LONG := p_list || ','; 
    l_comma_index PLS_INTEGER; 
    l_index  PLS_INTEGER := 1; 
BEGIN 
    LOOP 
    l_comma_index := INSTR(l_string, ',', l_index); 
    EXIT WHEN l_comma_index = 0; 
    PIPE ROW (SUBSTR(l_string, l_index, l_comma_index - l_index)); 
    l_index := l_comma_index + 1; 
    END LOOP; 
    RETURN; 
END f_convert2; 
/

次に、匿名ブロックでは、employee_idsとlast_nameの値を別々に渡します。

SET SERVEROUTPUT ON 
DECLARE 
    TYPE temprec IS RECORD (employeeid employees.employee_id%TYPE, 
    lastname  employees.last_name%TYPE); 
    TYPE templist IS 
     TABLE OF temprec; 
    vemplist  templist; 
    v_no_of_rec NUMBER := 10; 

    v_empl_ids VARCHAR2(100) := '&empl_ids'; 
    v_empl_lnames VARCHAR2(100) := '&empl_lnames'; 
BEGIN 
SELECT employee_id,last_name 
    BULK COLLECT 
INTO 
    vemplist 
FROM 
    (
     SELECT 
      ROWNUM rn, 
      column_value employee_id 
     FROM 
      TABLE (f_convert2(v_empl_ids)) 
    ) a 
    JOIN (
     SELECT 
      ROWNUM rn, 
      column_value last_name 
     FROM 
      TABLE (f_convert2(v_empl_lnames)) 
    ) b ON a.rn = b.rn; 

     FOR i in 1..vemplist.COUNT LOOP 
     DBMS_OUTPUT.PUT_LINE(vemplist(i).employeeid || ' ' ||vemplist(i).lastname); 
     END LOOP; 
END; 
/

代わりの簡単なあなたはOUTER JOINFULLまたはLEFT)を使用する場合は、それぞれの値をチェックするためのロジックを記述することなく、欠損値を扱うことができる上記のJOIN。

+0

ありがとうKaushik。私はこれを試してみる。実際に私は自分のデータベースへのアクセスを読んでいるだけでなく、私は匿名ブロックしか書くことができません。私の入力は従業員IDです(複数の値を一度に) – Veeresh

+0

この場合、宣言でTYPEと関数を定義できます。 –

+0

上記のコードを試したところ、次のエラーが発生しました。 PLS-00231:関数 'F_CONVERT2'はSQLでは使用できません – Veeresh

関連する問題