我被这个查询困住了

时间:2020-03-02 03:47:28

标签: sql oracle plsql

在此查询中,我想插入关联的数组元素输出,该输出打印在表phonebook中分为三列的电话号码,并将此输出插入此表中。

CREATE TABLE Phonebook 
(
      areacode  VARCHAR2(3),
      prefix    VARCHAR2(3),
      num   VARCHAR2(4)
);

SET SERVEROUTPUT ON
DECLARE
    TYPE phone_num IS RECORD (
     arac Phonebook.areacode%TYPE, prf Phonebook.prefix%TYPE, recnum phonebook.num%TYPE); 

    TYPE phonenum IS TABLE OF phone_num INDEX BY BINARY_INTEGER;

    aaaray phonenum;
    aaaray2 phonenum;

    CURSOR c IS 
    SELECT phone_number 
    from employees
    where department_id IN (20,80,90);
    diff INTEGER := 0;
BEGIN
    for i in c loop
    diff := diff + 1;
    IF  SUBSTR (i.phone_number, 1, 3 ) = '011' then 
    DBMS_OUTPUT.PUT_LINE('International');

    ELSIF  SUBSTR (i.phone_number, 1, 3 ) = '515' then 
    aaaray(diff).arac := SUBSTR (i.phone_number, 1, 3 );
    aaaray(diff).prf    := SUBSTR (i.phone_number, 5, 3 );
    aaaray(diff).recnum       := SUBSTR (i.phone_number, 9, 4 );

    DBMS_OUTPUT.PUT_LINE('phone number is domestic ' || aaaray(diff).arac || aaaray(diff).prf || aaaray(diff).recnum);
    elsif SUBSTR (i.phone_number, 1, 3 ) = '603' then
    aaaray2(diff).arac := SUBSTR (i.phone_number, 1, 3 );
    aaaray2(diff).prf    := SUBSTR (i.phone_number, 5, 3 );
    aaaray2(diff).recnum       := SUBSTR (i.phone_number, 9, 4 );
    DBMS_OUTPUT.PUT_LINE('phone number is domestic ' || aaaray2(diff).arac|| aaaray2(diff).prf || aaaray2(diff).recnum);
else 
DBMS_OUTPUT.PUT_LINE('no display');
end if;  
end loop;
insert into Phonebook values (aaaray.arac, aaaray.prf, aaaray.recnum) ;

   insert into Phonebook values (aaaray2.arac, aaaray2.prf, aaaray2.recnum) ;
END;
/

错误:

错误报告
ORA-06550:第39行,第66列:
PLS-00302:必须声明组件“ RECNUM”
ORA-06550:第39行,第66列:
PL / SQL:ORA-00984:此处不允许使用列
ORA-06550:第39行第4列:

3 个答案:

答案 0 :(得分:0)

您正在尝试在电话簿表中插入数组。

替换以下内容:

insert into Phonebook values (aaaray.arac, aaaray.prf, aaaray.recnum) ;
insert into Phonebook values (aaaray2.arac, aaaray2.prf, aaaray2.recnum) ;

使用

For diff in 1..aaaray.count loop
     insert into Phonebook values (aaaray(diff).arac, aaaray(diff).prf, aaaray(diff).recnum) ;
     insert into Phonebook values (aaaray2(diff).arac, aaaray2(diff).prf, aaaray2(diff).recnum) ;
end loop;

答案 1 :(得分:0)

您可以将插入语句放入for循环中。如我所见,除了存储数据之外,您对collections变量没有做任何其他事情,您也可以只使用1个变量-

DECLARE
    TYPE phone_num IS RECORD (
     arac Phonebook.areacode%TYPE, prf Phonebook.prefix%TYPE, recnum phonebook.num%TYPE); 

    TYPE phonenum IS TABLE OF phone_num INDEX BY BINARY_INTEGER;

    aaaray phonenum;

    CURSOR c IS 
    SELECT phone_number 
    from employees
    where department_id IN (20,80,90);
    diff INTEGER := 0;
BEGIN
    for i in c loop
    diff := diff + 1;
    IF  SUBSTR (i.phone_number, 1, 3 ) = '011' then 
    DBMS_OUTPUT.PUT_LINE('International');

    ELSIF  SUBSTR (i.phone_number, 1, 3 ) = '515' then 
    aaaray(diff).arac       := SUBSTR (i.phone_number, 1, 3 );
    aaaray(diff).prf        := SUBSTR (i.phone_number, 5, 3 );
    aaaray(diff).recnum     := SUBSTR (i.phone_number, 9, 4 );

    DBMS_OUTPUT.PUT_LINE('phone number is domestic ' || aaaray(diff).arac || aaaray(diff).prf || aaaray(diff).recnum);
    INSERT INTO Phonebook VALUES (aaaray(diff).arac, aaaray(diff).prf, aaaray(diff).recnum)) ;
    elsif SUBSTR (i.phone_number, 1, 3 ) = '603' then
      aaaray(diff).arac     := SUBSTR (i.phone_number, 1, 3 );
      aaaray(diff).prf      := SUBSTR (i.phone_number, 5, 3 );
      aaaray(diff).recnum   := SUBSTR (i.phone_number, 9, 4 );
      DBMS_OUTPUT.PUT_LINE('phone number is domestic ' || aaaray(diff).arac|| aaaray(diff).prf || aaaray(diff).recnum);
      INSERT INTO Phonebook VALUES (aaaray(diff).arac, aaaray(diff).prf, aaaray(diff).recnum) ;
    else 
      DBMS_OUTPUT.PUT_LINE('no display');
    end if;
  end loop;
  COMMIT;
END;
/

答案 2 :(得分:0)

有一些更改可以简化并加快操作速度。 具体来说,请使用Phonebook表本身来定义记录,并使用FORALL语法和基于记录的插入。

这是设置:

CREATE TABLE Phonebook 
(
      areacode  VARCHAR2(3),
      prefix    VARCHAR2(3),
      num   VARCHAR2(4)
);
create table Employees
(
      employee_id number,
      name varchar2(100),
      department_id number,
      phone_number varchar2(30)
);
insert into employees values(1, 'George Washington', 20, '515-123-4567');
insert into employees values(2, 'Harry Truman', 20, '603-123-4567');
insert into employees values(3, 'Andrew Jackson', 80, '313-123-4567');
insert into employees values(4, 'Millard Fillmore', 90, '011-12-34567890');

commit;

用对表本身的引用替换代码中记录类型的定义:

    -- no need to define the record before, just use phonebook%rowtype
    TYPE phonenum IS TABLE OF phonebook%rowtype INDEX BY BINARY_INTEGER;

    aaaray phonenum;
    aaaray2 phonenum;

修正对记录列的引用以匹配目标表

    aaaray(diff).arac       := SUBSTR (i.phone_number, 1, 3 );
    aaaray(diff).prf        := SUBSTR (i.phone_number, 5, 3 );
    aaaray(diff).recnum     := SUBSTR (i.phone_number, 9, 4 );
...becomes...
    aaaray(diff).areacode  := SUBSTR (i.phone_number, 1, 3 );
    aaaray(diff).prefix    := SUBSTR (i.phone_number, 5, 3 );
    aaaray(diff).num       := SUBSTR (i.phone_number, 9, 4 );

并将INSERT语句替换为FORALL,其中包含INSERT的完整记录:

forall i in aaaray.FIRST..aaaray.LAST
  insert into Phonebook values aaaray(i);
forall i in aaaray2.FIRST..aaaray2.LAST
  insert into Phonebook values aaaray2(i);

FORALL关键字使Oracle准备好插入的完整列表,然后一次性将它们发送到数据库,而不是为每个记录进行上下文切换。这样效率更高。 因为我们基于表定义了记录,所以我们可以直接插入它们,而无需单独引用字段。

如果表具有数十个字段,这将使工作变得更加轻松。

这是您的代码的完整修改版:

DECLARE
    TYPE phonenum IS TABLE OF phonebook%rowtype INDEX BY BINARY_INTEGER;

    aaaray phonenum;
    aaaray2 phonenum;

    CURSOR c IS
    SELECT phone_number 
    from employees
    where department_id IN (20,80,90);
    diff INTEGER := 0;
BEGIN
    for i in c loop
    diff := diff + 1;
    IF  SUBSTR (i.phone_number, 1, 3 ) = '011' then 
    DBMS_OUTPUT.PUT_LINE('International');

    ELSIF  SUBSTR (i.phone_number, 1, 3 ) = '515' then 
    aaaray(diff).areacode  := SUBSTR (i.phone_number, 1, 3 );
    aaaray(diff).prefix    := SUBSTR (i.phone_number, 5, 3 );
    aaaray(diff).num       := SUBSTR (i.phone_number, 9, 4 );

    DBMS_OUTPUT.PUT_LINE('phone number is domestic ' || aaaray(diff).areacode || aaaray(diff).prefix || aaaray(diff).num);
    elsif SUBSTR (i.phone_number, 1, 3 ) = '603' then
    aaaray2(diff).areacode := SUBSTR (i.phone_number, 1, 3 );
    aaaray2(diff).prefix   := SUBSTR (i.phone_number, 5, 3 );
    aaaray2(diff).num      := SUBSTR (i.phone_number, 9, 4 );
    DBMS_OUTPUT.PUT_LINE('phone number is domestic ' || aaaray2(diff).areacode|| aaaray2(diff).prefix || aaaray2(diff).num);
else 
DBMS_OUTPUT.PUT_LINE('no display');
end if;  
end loop;
forall i in aaaray.FIRST..aaaray.LAST
  insert into Phonebook values aaaray(i);
forall i in aaaray2.FIRST..aaaray2.LAST
  insert into Phonebook values aaaray2(i);
END;
/