2

I am a beginner in PL/SQL. I want to run simple WHILE LOOP and I am receiving errors.

Here is my code:

DECLARE
  counter INTEGER := 01;
BEGIN
  WHILE counter <= 30 
  LOOP
    SELECT name, count(iid) as Counts
    FROM table.orders
    WHERE date_inserted >= TO_DATE('14-SEP-16 12.00.00 AM','DD-MON-YY HH.MI.SS AM')
    AND date_inserted <= TO_DATE('14-SEP-16 12.'counter'.00 PM','DD-MON-YY HH.MI.SS AM')
    HAVING count(iid) >= 60
    ORDER BY count(iid) DESC;
  END LOOP;
END;

I am getting these errors when running the code:

*Error starting at line : 1 in command -
DECLARE
  counter INTEGER := 01;
BEGIN
  WHILE counter <= 30 
  LOOP
    SELECT iname, count(iid) as Counts
    FROM table.orders
    WHERE date_inserted >= TO_DATE('14-SEP-16 12.00.00 AM','DD-MON-YY HH.MI.SS AM')
    AND date_inserted <= TO_DATE('14-SEP-16 12.'counter'.00 PM','DD-MON-YY HH.MI.SS AM')
    HAVING count(iid) >= 60
    ORDER BY count(iid) DESC;
  END LOOP;
END;

Error report - ORA-06550: line 9, column 49:
PL/SQL: ORA-00907: missing right parenthesis
ORA-06550: line 6, column 5:
PL/SQL: SQL Statement ignored
06550. 00000 - "line %s, column %s:\n%s"
Cause: Usually a PL/SQL compilation error.
Action:

What seems to be the problem? Thanks in advance!

7
  • Can you reformat your question so that it appears as fixed text by indenting it? It's hard to read in paragraph form. Commented Sep 14, 2016 at 2:43
  • TO_DATE('14-SEP-16 12.' + counter + '.00 PM','DD-MON-YY HH.MI.SS AM') Commented Sep 14, 2016 at 2:45
  • Wait, I will edit it. Thanks! Commented Sep 14, 2016 at 2:45
  • artm - will this work also... TO_DATE('14-SEP-16 12.'||TO_CHAR(counter)|| + '.00 PM','DD-MON-YY HH.MI.SS AM') Commented Sep 14, 2016 at 2:52
  • I never initialize my variables in oracle above the first BEGIN line. I do not know why I do that however. Commented Sep 14, 2016 at 2:53

4 Answers 4

3

Don't concatenate, it would be more efficient (and in my opinion easier to read) if you simply add the counter to a proper date value. You also don't increment the counter and you are missing the group by in the query. And finally, the result of a query must be stored somewhere.

DECLARE
  counter INTEGER := 1;
  l_from_date DATE;
  l_name varchar(200);
  l_count integer;
BEGIN
  from_date := TO_DATE('14-SEP-16 12.00.00 AM','DD-MON-YY HH.MI.SS AM');

  WHILE counter <= 30 
  LOOP
    SELECT name, count(iid) as Counts
       into l_name, l_count --<< store the result somewhere
    FROM table.orders 
    WHERE date_inserted >= l_from_date 
    AND date_inserted <= l_from_date + counter
    GROUP BY name --<< this was missing as well
    HAVING count(iid) >= 60
    ORDER BY count(iid) DESC;

    counter := counter + 1;  --<< increment the counter

    -- do something with l_name and l_count ....
  END LOOP;
END;
/

Unrelated to this question: but you should avoid NLS specific format strings for date values. Better use a format that doesn't depend on the language used by the SQL client (or application) running the code. e.g. to_date('2016-09-14 00:00:00', 'yyyy-mm-dd hh24:mi:ss')

Sign up to request clarification or add additional context in comments.

4 Comments

Good advice, but date '2016-09-14 is a lot less bother.
@WilliamRobertson: I know and I prefer the ANSI literals myself - I just don't wanted to introduce yet another "new" thing (seeing that the OP is clearly a newcomer)
Sorry but AND date_inserted <= l_from_date + counter would add a whole day. I think what the OP really wants is AND date_inserted <= l_from_date + counter/1440 (1440 being the number of minutes in a day).
@archimede: No idea. But I'd prefer using l_from_date + interval '1' minute * counter in that case (to make intentions clear)
0

You would want to use CONCAT or || after converting counter to char in order to add it in between those strings.

Comments

0

In your code, I don't see you increment the counter. Is it by design??

To answer your question, as mentioned in comments, you would want to use concat for concatenating the string. Change your where condition to

WHERE date_inserted >= TO_DATE('14-SEP-16 12.00.00 AM','DD-MON-YY HH.MI.SS AM')
AND date_inserted <= TO_DATE('14-SEP-16 12.'||to_char(counter)||'.00 PM','DD-MON-YY HH.MI.SS AM')

In fact in Oracle 11 or newer versions (may be previous too but I never worked on those), you don't need to do conversions explicitly. So you can directly concatenate counter to the string.

WHERE date_inserted >= TO_DATE('14-SEP-16 12.00.00 AM','DD-MON-YY HH.MI.SS AM')
AND date_inserted <= TO_DATE('14-SEP-16 12.'||counter||'.00 PM','DD-MON-YY HH.MI.SS AM')

3 Comments

Oracle has supported implicit conversions since many versions ago.
Oracle has always supported implicit conversions, as have all mainstream SQL vendors.
that's why I explicitly mentioned (may be previous too but I never worked on those). Thanks for confirming it.
0

You can concatenate the strings directly

WHERE date_inserted >= TO_DATE('14-SEP-16 12.00.00 AM','DD-MON-YY HH.MI.SS AM')
AND date_inserted <= TO_DATE('14-SEP-16 12.'||counter||'.00 PM','DD-MON-YY HH.MI.SS AM')

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.