Проблема в использовании курсора с параметрами - PullRequest
0 голосов
/ 26 февраля 2020

Я использую курсор с обоими входными и выходными параметрами для извлечения данных из запроса на выборку и вставки в другую таблицу с интервалами: -

DECLARE

  i_start_date varchar2(20) := '2019-01-02';
  i_end_date varchar2(20):= '2019-01-09';
  v_ack_records record_inst%ROWTYPE;

  CURSOR record_inst(i_start_date varchar2,i_end_date varchar2) IS
  select a.id,b.status
  from table1.a,table2 b
  on a.msg_id=b.msg_id
  and b.t_date>=i_start_date 
  and b.t_date<=i_end_date ;

BEGIN
    OPEN record_inst; 
    LOOP
      FETCH record_inst INTO v_ack_records;
      EXIT WHEN record_inst%NOTFOUND;
      INSERT INTO test_table
        (id,status)
      VALUES(v_ack_records.id,
             v_ack_records.status);

    END LOOP;
    CLOSE record_inst;
    COMMIT; 
END; 
/

Я не совсем ясно, какой синтаксис использовать для это. Не могли бы вы помочь в этом? Я получил следующие ошибки: -

[Error Code: 6550, SQL State: 65000]  ORA-06550: line 5, column 15:
PLS-00320: the declaration of the type of this expression is incomplete or malformed
ORA-06550: line 5, column 15:
PL/SQL: Item ignored
ORA-06550: line 14, column 5:
PLS-00306: wrong number or types of arguments in call to 'RECORD_INST'
ORA-06550: line 14, column 5:
PL/SQL: SQL Statement ignored
ORA-06550: line 16, column 28:
PLS-00320: the declaration of the type of this expression is incomplete or malformed
ORA-06550: line 16, column 5:
PL/SQL: SQL Statement ignored
ORA-06550: line 22, column 15:
PL/SQL: ORA-00984: column not allowed here
ORA-06550: line 18, column 1:
PL/SQL: SQL Statement ignored

Дата начала и дата окончания являются входами, а id и статус являются выходами.

Спасибо,

1 Ответ

0 голосов
/ 26 февраля 2020

Это очень упрощенный код, который вы написали; Для вашего случая важен раздел declare.

SQL> declare
  2    v_emp_rec    record_emp%rowtype;
  3
  4    cursor record_emp is
  5      select empno, ename from emp;
  6  begin
  7    null;
  8  end;
  9  /
  v_emp_rec    record_emp%rowtype;
               *
ERROR at line 2:
ORA-06550: line 2, column 16:
PLS-00320: the declaration of the type of this expression is incomplete or
malformed
ORA-06550: line 2, column 16:
PL/SQL: Item ignored


SQL>

Как видите, та же ошибка, что и у вас. Почему? Потому что вы сначала объявили переменную курсора - которая основана на определении курсора - но курсор еще не был объявлен. Другими словами, должно быть наоборот: курсор первый, переменная следующая:

SQL> declare
  2    cursor record_emp is
  3      select empno, ename from emp;
  4
  5    v_emp_rec    record_emp%rowtype;
  6    begin
  7    null;
  8  end;
  9  /

PL/SQL procedure successfully completed.

SQL>

Кроме того, вам не нужно использовать такой сложный код; простой insert делает свою работу. Обратите внимание на способ, которым я объявлял переменные - их тип данных date, как это, вероятно, и должно быть, если только b.t_date тип данных столбца не varchar2. Если это так, то у вас есть большая проблема, чем порядок в разделе объявлений. Никогда не храните даты в виде строк.

Кроме того, вы должны переключиться на явные объединения вместо oldfashioned from, где все таблицы разделены запятыми и где объединения смешаны с условиями. Ваш код несколько странный, поскольку он содержит ключевое слово on, но без join и where, поэтому ... это не сработает.

declare
  i_start_date  date := date '2019-01-02';    -- date literal is always YYYY-MM-DD
  i_end_date    date := date '2019-01-09';
begin  
  insert into test_table (id, status)
    select a.id, b.status
    from table1 a join table2 b on a.msg_id = b.msg_id
    where b.t_date between i_start_date and i_end_date;
end;
/

Если вы хотите использовать курсор, рассмотрите курсор FOR l oop, так как он намного проще в использовании; Oracle выполняет большую часть работы dirty за вас (открытие курсора, выборка из него, внимание при выходе из l oop, закрытие курсора):

declare
  i_start_date  date := date '2019-01-02';
  i_end_date    date := date '2019-01-09';
begin  
  for cur_r in (select a.id, b.status
                from table1 a join table2 b on a.msg_id = b.msg_id
                where b.t_date between i_start_date and i_end_date
               )
  loop
    insert into test_table (id, status)
      values (cur_r.id, cur_r.status);
  end loop;
end;
/

Если вы все еще хотите сделать это по-своему, пожалуйста, сделайте это. Остальная часть вашей процедуры выглядит нормально (не могу проверить, у меня нет ваших таблиц).

...