Выбрать оператор внутри цикла - PullRequest
0 голосов
/ 04 февраля 2020

Я пытаюсь поместить свой оператор select внутри a для l oop, и после зацикливания я хочу вставить результат в таблицу, но при выполнении я сталкиваюсь с этой ошибкой.

ORA-06550: строка 5, столбец 7:
PLS-00428: в этом операторе SELECT ожидается предложение INTO

Так что мой запрос выглядит следующим образом. После цикла я хочу вставить результат в таблицу.

BEGIN
  for cur_rec in (Select Distinct SDESCRIPTION from TB_READER where SDESCRIPTION is not null and SDESCRIPTION not Like '%IN%' and SDESCRIPTION not like '%OUT%') 
   loop

      SELECT L.NEVENTLOGIDN, LPAD (nuserid, 6, '0') nuserid, u.susername, 
    TO_CHAR (TO_DATE ('1970-01-01 00:00:00', 'YYYY-MM-DD HH24:MI:SS') + ( (ndatetime) / (60 * 60 * 24)), 'YYYY-MM-DD HH24:MI:SS') 
    date_time, l.nreaderidn, r.sname, 
    CASE WHEN l.nreaderidn IN (SELECT nreaderidn FROM tb_reader where sdescription = cur_rec.SDESCRIPTION and upper(sname) like '%' || upper('OUT') || '%') THEN 'OUT' 
    WHEN l.nreaderidn  IN (SELECT nreaderidn FROM tb_reader where sdescription = cur_rec.SDESCRIPTION and upper(sname) like '%' || upper('IN') || '%') THEN 'IN' END logtype 
   FROM TB_EVENT_LOG l, TB_READER r, TB_USER u 
   WHERE 
   l.nreaderidn IN (SELECT nreaderidn FROM tb_reader where sdescription = cur_rec.SDESCRIPTION) 
   AND NDATETIME >= (trunc(sysdate -1) - TO_DATE ('1970-01-01 12:00:00 AM', 'YYYY-MM-DD HH:MI:SS AM')) * 24 * 60 * 60 
   AND ndatetime <= (trunc(sysdate) - TO_DATE ('1970-01-01 12:00:00 AM', 'YYYY-MM-DD HH:MI:SS AM')) * 24 * 60 * 60 
   AND l.nuserid = u.suserid 
   AND l.nreaderidn = r.nreaderidn                           
   ORDER BY 2, 4;


   end loop;

 END;
 /

Ответы [ 2 ]

3 голосов
/ 04 февраля 2020

Блок кода BEGIN ... END; обычно называют «анонимным блоком».

Здесь важно понимать, что это не просто ванильный SQL, а скорее PL/SQL код, т.е. внутри в этом блоке вы пишете процедурный код (PL / SQL означает процедурный язык для SQL).

Когда вы выполняете простой запрос SQL, например SELECT columns FROM table, вне анонимного блока базы данных Движок вернет данные из этого запроса в инструмент, который вы используете для его выполнения. Но здесь вы пишете код (который включает в себя SQL), и когда он выполняется, где результаты этого запроса go? Как программа узнает, куда отправить эти результаты?

Хотя большая часть PL/SQL включает в себя написание SQL, а затем выполнение некоторых других задач, и во многих случаях это синоним SQL в том смысле, что многие ключевые слова и встроенные функции имеют одинаковые имена, Стоит помнить, что PL/SQL и SQL являются двумя разными средами и работают немного по-разному.

Вы можете увидеть разницу в сообщениях об ошибках: ORA-##### исходит от механизма базы данных, где PLS-##### исходит от движка PL / SQL.

В любом случае, я надеюсь, что эта справочная информация была полезной. Специфическая проблема c, с которой вы столкнулись, заключается в том, что ваша программа не знает, где хранить выходные данные запроса, поэтому вам нужно определить некоторые локальные переменные, а затем сохранить результаты вашего SELECT оператора INTO этих локальных переменных. , При использовании оператора SELECT ... INTO вы должны быть уверены, что когда-нибудь вернете только одну строку, иначе вы получите другую ошибку. (Вы можете использовать курсор, если ваш оператор может вернуть более одной строки, тогда у вас также будет внутренний l oop).

DECLARE
  /* apologies for the quick and dirty example here; 
   * you'd want to use better variable names and correct data types and lengths
   */
  s1 VARCHAR2(100 CHAR);
  s2 VARCHAR2(100 CHAR);
  s3 VARCHAR2(100 CHAR);
  s4 VARCHAR2(100 CHAR);
  s5 VARCHAR2(100 CHAR);
  s6 VARCHAR2(100 CHAR);
  s7 VARCHAR2(100 CHAR);
BEGIN
  for cur_rec in (Select Distinct SDESCRIPTION
                    from TB_READER 
                   where SDESCRIPTION is not null 
                     and SDESCRIPTION not Like '%IN%' 
                     and SDESCRIPTION not like '%OUT%') 
   loop

      SELECT L.NEVENTLOGIDN, 
             LPAD (nuserid, 6, '0') nuserid,
             u.susername, 
             TO_CHAR (TO_DATE ('1970-01-01 00:00:00', 'YYYY-MM-DD HH24:MI:SS') + ( (ndatetime) / (60 * 60 * 24)), 'YYYY-MM-DD HH24:MI:SS') date_time, 
             l.nreaderidn, 
             r.sname, 
             CASE WHEN l.nreaderidn IN (SELECT nreaderidn 
                                          FROM tb_reader 
                                          where sdescription = cur_rec.SDESCRIPTION 
                                            and upper(sname) like '%' || upper('OUT') || '%') THEN 'OUT' 
                  WHEN l.nreaderidn IN (SELECT nreaderidn 
                                          FROM tb_reader 
                                         where sdescription = cur_rec.SDESCRIPTION 
                                           and upper(sname) like '%' || upper('IN') || '%') THEN 'IN' END logtype 
    INTO s1, s2, s3, s4, s5, s6, s7
    FROM TB_EVENT_LOG l, TB_READER r, TB_USER u 
   WHERE l.nreaderidn IN (SELECT nreaderidn 
                            FROM tb_reader 
                           where sdescription = cur_rec.SDESCRIPTION) 
     AND NDATETIME >= (trunc(sysdate -1) - TO_DATE ('1970-01-01 12:00:00 AM', 'YYYY-MM-DD HH:MI:SS AM')) * 24 * 60 * 60 
     AND ndatetime <= (trunc(sysdate) - TO_DATE ('1970-01-01 12:00:00 AM', 'YYYY-MM-DD HH:MI:SS AM')) * 24 * 60 * 60 
     AND l.nuserid = u.suserid 
     AND l.nreaderidn = r.nreaderidn                           
   ORDER BY 2, 4;


   end loop;

 END;
 /
2 голосов
/ 04 февраля 2020

Когда вы используете одноэлементный SELECT для извлечения данных из базы данных, вам необходимо предоставить соответствующие объявления переменных и предложение INTO, чтобы сообщить оператору SELECT, куда поместить значения, которые он получает. Например:

DECLARE
  vNeventlogidn          TB_EVENT_LOG.NEVENTLOGIDN%TYPE;
  vUserid                VARCHAR2(30);
  vSusername             TB_USER.SUSERNAME%TYPE;
  vDate_time             VARCHAR2(50);
  vNreaderidn            TB_EVENT_LOG.NREADERIDN%TYPE;
  vSname                 TB_READER.SNAME%TYPE;
  vLogtype               VARCHAR2(3);
BEGIN
  for cur_rec in (Select Distinct SDESCRIPTION
                    from TB_READER
                    where SDESCRIPTION is not null and
                          SDESCRIPTION not Like '%IN%' and
                          SDESCRIPTION not like '%OUT%') 
   loop
     SELECT L.NEVENTLOGIDN,
            LPAD (nuserid, 6, '0') nuserid,
            u.susername, 
            TO_CHAR (TO_DATE ('1970-01-01 00:00:00', 'YYYY-MM-DD HH24:MI:SS') + ( (ndatetime) / (60 * 60 * 24)), 'YYYY-MM-DD HH24:MI:SS') date_time,
            l.nreaderidn,
            r.sname, 
            CASE
              WHEN l.nreaderidn IN (SELECT nreaderidn
                                      FROM tb_reader
                                      where sdescription = cur_rec.SDESCRIPTION and 
                                            upper(sname) like '%' || upper('OUT') || '%')
                THEN 'OUT' 
              WHEN l.nreaderidn IN (SELECT nreaderidn
                                      FROM tb_reader
                                      where sdescription = cur_rec.SDESCRIPTION and
                                            upper(sname) like '%' || upper('IN') || '%')
                THEN 'IN'
            END logtype 
       INTO vNeventlogidn,
            vUserid,
            vSusername,
            vDate_time,
            vNreaderidn,
            vSname,
            vLogtype
       FROM TB_EVENT_LOG l,
            TB_READER r,
            TB_USER u 
       WHERE l.nreaderidn IN (SELECT nreaderidn
                                FROM tb_reader
                                where sdescription = cur_rec.SDESCRIPTION) AND
             NDATETIME >= (trunc(sysdate -1) - TO_DATE ('1970-01-01 12:00:00 AM', 'YYYY-MM-DD HH:MI:SS AM')) * 24 * 60 * 60 AND
             ndatetime <= (trunc(sysdate) - TO_DATE ('1970-01-01 12:00:00 AM', 'YYYY-MM-DD HH:MI:SS AM')) * 24 * 60 * 60 AND
             l.nuserid = u.suserid AND
             l.nreaderidn = r.nreaderidn                           
       ORDER BY 2, 4;
   end loop;
 END;
...