如何一次读取多个值作为PLSQL中单个变量的输入?

How to read multiple values at one time as an input to single variable in PLSQL?

你能帮我传递输入值吗(在执行时:我的意思是一次为单个变量输入多个值)。

这是我的代码,我一次给出一个输入,要么是硬编码输入,要么是一次输入。

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;
/

以上程序一次取一个输入值。 但是,我尝试了如下但无法成功。

我尝试一次从控制台提供输入,例如 (100,34,104,100),而不是对输入进行硬编码(或)一次提供一个输入。

DECLARE 部分中的代码段:

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;

在最后的 BEGIN 部​​分:

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;
/

DECLARE 部分错误: PLS-00306: 调用 'TEMPLIST' 时参数的数量或类型错误 LAST BEGIN 部​​分错误: PLS-00320: 此表达式的类型声明不完整或格式错误

例如: 有时,我能够读取同一个变量的多个输入值,但我无法将其作为输入传递,但无法弄清楚如何才能将其作为我的主程序的输入。

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 程序成功完成。 输入订单值:321,153,678

321 153 678

谢谢。

因为你有一个record变量的集合,你需要分别传递employee_ids和员工last_names。你打算如何一次性超越他们? 这是一个示例脚本,它使用 3 个集合元素的 2 个输入完成你想要的东西。

首先,创建一个集合 TYPE 和一个 PIPELINED function 将逗号分隔值转换为 Collections - f_convert2.

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 JOINFULLLEFT),而不是上面的简单 JOIN,您可以处理缺失值而无需编写逻辑来检查每个值。