Я застрял с этим запросом - PullRequest
0 голосов
/ 02 марта 2020

В этом запросе я хочу вставить вывод элементов ассоциативного массива, который печатает номер телефона, разделенный на три столбца в таблице 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 голосов
/ 02 марта 2020

Вы можете поместить свой оператор вставки внутрь для l oop. Как я вижу, вы ничего не делаете с вашими переменными коллекций, кроме хранения данных, вы также можете использовать только 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;
/
0 голосов
/ 02 марта 2020

Есть несколько изменений, которые могут упростить и ускорить процесс. В частности, используйте саму таблицу 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;
/
0 голосов
/ 02 марта 2020

Вы пытаетесь вставить массив в таблицу телефонной книги.

Замените следующее:

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