Sql I';我被这个问题难住了

Sql I';我被这个问题难住了,sql,oracle,plsql,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.area

在这个查询中,我想插入关联数组元素输出,它在表
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列:


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

替换以下内容:

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


您可以将insert语句放入for循环中。正如我所看到的,除了存储数据之外,您没有在收集变量方面做任何其他事情,您也可以只使用一个变量-

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

有一些改变可以简化和加速事情。 具体来说,使用
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
wrapping
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;
/
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;
/