Skip to content
Advertisement

Select statement inside for loop

I’m trying to put my select statement inside a for loop and after looping I want to insert the result on a table but upon my execution I bump in to this error.

ORA-06550: line 5, column 7:
PLS-00428: an INTO clause is expected in this SELECT statement

So my query goes like this. After looping I want to insert the result on a table.

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

Advertisement

Answer

A BEGIN ... END; block of code is commonly referred to as an “anonymous block.”

It’s important to understand here that this is not just entirely vanilla SQL but rather PL/SQL code i.e. within this block you are writing procedural code (PL/SQL stands for Procedural Language for SQL).

When you execute a simple SQL query such as SELECT columns FROM table outside of an anonymous block the database engine will return the data from that query to the tool you are using to execute it. But here you are writing code (which happens to include SQL) and when it executes, where do the results of that query go? How does the program know where to send those results?

While a large chunk of PL/SQL involves writing SQL and then performing some other tasks, and in many cases it is synonymous with SQL in that many keywords and built in functions have the same names, it’s worth keeping this in mind that PL/SQL and SQL are two different environments and work slightly differently.

You can see the difference in error messages: ORA-##### comes from the database engine where as PLS-##### comes from the PL/SQL engine.

Anyways, I hope this background information was helpful. The specific problem you are having is that your program does not know where to store the output of the query, so you need to define some local variables and then store the results of your SELECT statement INTO those local variables. When using a SELECT ... INTO statement you need to be sure you only ever return one row, otherwise you’ll get a different error. (You can use a cursor if your statement might return more than one row, then you’d have an inner loop as well).

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;
 /
User contributions licensed under: CC BY-SA
3 People found this is helpful
Advertisement