Я все время получаю синтаксическую ошибку, как мне ее решить?

#oracle #plsql

Вопрос:

 DECLARE
   c_id c_customer.customer_name%type;
   coin_id1 i_invoice.coin_id%type;
   coin_price c_coin.price%type;
   delivery  i_invoice.delivery_date%type;
   CURSOR i_invoice ,c_coin ,c_customer is
      SELECT customer_name, coin_id, price ,delivery_date
FROM ((invoice
INNER JOIN customer on invoice.customer_id = customer.customer_id)
  INNER JOIN coin on invoice coin_id = coin.coin_id)
WHERE delivery_date BETWEEN '18 MAY 2021' AND  '20 MAY 2021'

BEGIN

   OPEN i_invoice,c_customer,c_coin;
   LOOP

   FETCH c_customers into customer_id ,
         c_coin into coin_id,
         c_coin into price,
         i_invoice into delivery_date;

   EXIT WHEN i_invloice%notfound;

   dbms_output.put_line(customer_id || ' ' || coin_id || ' ' 
                                    || price || ' ' || delivery_date);

   END LOOP;

   CLOSE i_invoice;

END;
/
 

Комментарии:

1. В чем заключается ошибка, которую вы получаете? Хотя ваше объявление курсора неверно.

2. Один из возможных источников ошибок: сравнение delivery_date со строками . Вы должны преобразовать их в даты: to_date('18 MAY 2021', 'dd MON yyyy') . Очень распространенная ошибка новичка (но тоже очень дорогая).

3. ошибка возникает при объявлении курсора

4. кто-нибудь, пожалуйста, может исправить мою декларацию курсора?

Ответ №1:

Ты устроил довольно большой беспорядок. Позвольте мне попробовать выбрать некоторые ошибки:

  • в declare разделе вы используете одни имена таблиц ( i_invoice , c_coin ), в то время from как предложение курсора предполагает другие ( invoice , coin )
  • например, курсор должен иметь имя c1 . Его имени не может быть i_invoice ,c_coin ,c_customer . Вы бы на самом деле ввели курсор в эти переменные
  • where предложение неверно — если delivery_date тип данных столбца date (я предполагаю, что это так, как и должно быть), то не сравнивайте его со строками. '18 MAY 2021' это струна. Литерал даты (я использовал) не является
  • open это так же неправильно, как объявление курсора; вы бы open c1
  • fetch также потерпел бы неудачу, поскольку customer_id в его select списке столбцов нет. Кроме того, почему вы лезете c_coin в оба coin_id и price ?

Я бы посоветовал вам for вместо этого использовать цикл курсора. Вам не нужно явно объявлять какие-либо переменные, открывать курсор, извлекать переменные, заботиться о выходе из цикла или закрытии курсора. Что-то вроде этого (с фиктивными таблицами, которые я создал, просто чтобы показать, что код компилируется):

 SQL> alter session set nls_date_format = 'dd.mm.yyyy';

Session altered.
 

Описание:

 SQL> desc customer
 Name                                      Null?    Type
 ----------------------------------------- -------- ----------------------------
 CUSTOMER_NAME                                      VARCHAR2(10)
 CUSTOMER_ID                                        NUMBER

SQL> desc invoice
 Name                                      Null?    Type
 ----------------------------------------- -------- ----------------------------
 COIN_ID                                            NUMBER
 DELIVERY_DATE                                      DATE
 CUSTOMER_ID                                        NUMBER

SQL> desc coin
 Name                                      Null?    Type
 ----------------------------------------- -------- ----------------------------
 PRICE                                              NUMBER
 COIN_ID                                            NUMBER
 

Содержание:

 SQL> select * from customer;

CUSTOMER_N CUSTOMER_ID
---------- -----------
Littlefoot           1

SQL> select * from invoice;

   COIN_ID DELIVERY_D CUSTOMER_ID
---------- ---------- -----------
         1 19.05.2021           1

SQL> select * from coin;

     PRICE    COIN_ID
---------- ----------
       100          1
 

Сам код:

 SQL> set serveroutput on
SQL> begin
  2    for cur_r in (select t.customer_id,
  3                         t.customer_name,
  4                         c.coin_id,
  5                         c.price,
  6                         i.delivery_date
  7                  from invoice i join customer t on i.customer_id = t.customer_id
  8                                 join coin c     on i.coin_id     = c.coin_id
  9                  where i.delivery_date between date '2021-05-18' and date '2021-05-20'
 10                 )
 11    loop
 12      dbms_output.put_line(cur_r.customer_id
 13                           || ' '
 14                           || cur_r.coin_id
 15                           || ' '
 16                           || cur_r.price
 17                           || ' '
 18                           || cur_r.delivery_date);
 19    end loop;
 20  end;
 21  /
1 1 100 19.05.2021

PL/SQL procedure successfully completed.

SQL>
 

Если вы настаиваете на том, чтобы сделать это по-своему, по крайней мере, объявите одну переменную курсора вместо отдельных переменных.

 SQL> declare
  2    cursor c1 is
  3      select t.customer_id,
  4                         t.customer_name,
  5                         c.coin_id,
  6                         c.price,
  7                         i.delivery_date
  8                  from invoice i join customer t on i.customer_id = t.customer_id
  9                                 join coin c     on i.coin_id     = c.coin_id
 10                  where i.delivery_date between date '2021-05-18' and date '2021-05-20';
 11    cur_r c1%rowtype;
 12  begin
 13    open c1;
 14    loop
 15      fetch c1 into cur_r;
 16      exit when c1%notfound;
 17
 18      dbms_output.put_line(cur_r.customer_id
 19                           || ' '
 20                           || cur_r.coin_id
 21                           || ' '
 22                           || cur_r.price
 23                           || ' '
 24                           || cur_r.delivery_date);
 25    end loop;
 26  end;
 27  /
1 1 100 19.05.2021

PL/SQL procedure successfully completed.

SQL>
 

Ответ №2:

Вы используете неправильный синтаксис для объявления курсора. Правильный код должен выглядеть одинаково —

 DECLARE
       c_id c_customer.customer_name%type;
       coin_id1 i_invoice.coin_id%type;
       coin_price c_coin.price%type;
       delivery  i_invoice.delivery_date%type;
       -- CURSOR i_invoice ,c_coin ,c_customer is    --> This is incorrect declaration.
       CURSOR invoice_dtls IS
       SELECT customer_name, coin_id, price ,delivery_date
         FROM ((invoice INNER JOIN customer on invoice.customer_id = customer.customer_id)
               INNER JOIN coin on invoice coin_id = coin.coin_id)
        WHERE delivery_date BETWEEN '2021-05-18' AND  '2021-05-20'
       -- You are missing a semi-colon after this
       ;

BEGIN

   -- OPEN i_invoice,c_customer,c_coin;
   OPEN invoice_dtls;
   LOOP
   
   /*FETCH c_customers into customer_id ,
         c_coin into coin_id,
         c_coin into price,
         i_invoice into delivery_date;*/
   FETCH invoice_dtls
    INTO c_id, coin_id1, coin_price, delivery; 

   EXIT WHEN i_invloice%notfound;

   dbms_output.put_line(c_id || ' ' || coin_id1 || ' ' 
                        || coin_price || ' ' || delivery);

   END LOOP;
   CLOSE i_invoice;

END;
/
 

Комментарии:

1. продолжайте получать ошибку здесь: ОТКРОЙТЕ i_invoice,c_customer,c_coin;

2. Попробуйте мой отредактированный код. Я прокомментировал эту строку.

3. ошибка в вашем коде появляется здесь: ВЫБЕРИТЕ имя пользователя, идентификатор монеты, цену ,дату доставки

4. Попробуй сейчас. Я обновил формат даты.

5. @taahirmia — Даже при повторных исправлениях и корректировках вы, похоже, все еще сопротивляетесь публикации фактического сообщения об ошибке . Программное обеспечение выдает коды ошибок и текст сообщения по определенной причине. Пожалуйста, помогите тем, от кого вы ожидаете помощи, и опубликуйте сообщения об ошибках .