0

I want to grab a count of distinct ASN_NO's from my query to later check in my stored procedure if i find more than one and throw an error.

Instead of trying to open the cursor(which i was also failing at doing properly), i thought maybe i could do it with temp table selects and store the value while i'm populating the cursor. Maybe this isn't possible, but my error makes no sense to me.

Here is my simplified code, i broke the count statement out to identify better where exactly the error was.

V_ASN_COUNT           NUMBER;

OPEN O_CURSOR FOR  
  WITH O_LIST AS(
     SELECT *
       FROM AN_ORDER_INFO OI, AN_SHIPMENT_INFO SI
       -- where bunch of stuff
  ),   
  COUNT_ASN_NO AS  (
          SELECT COUNT(DISTINCT ASN_NO) AS "ASN_COUNT"
          FROM O_LIST 
  ),
  SAVE_ASN_COUNT AS (
   SELECT ASN_COUNT
   INTO V_ASN_COUNT
   FROM COUNT_ASN_NO -- error on this line, not enough values, its just 1:1, i dont get it?
  ) 
  SELECT * FROM O_LIST;   

IF(V_ASN_COUNT > 1) THEN
    RAISE MULTIPLE_ASNS;
END IF;   

Or perhaps i need to open the cursor afterwards and do something like this, except i know this is wrong, i get "expecting BULK INTO" error:

  OPEN O_CURSOR; 
      LOOP
          FETCH COUNT(DISTINCT ASN_NO) INTO V_ASN_COUNT;
          EXIT WHEN ASN_NO%NOTFOUND;
      END LOOP;
  CLOSE O_CURSOR;
SomeRandomDeveloper
  • 489
  • 2
  • 13
  • 33

1 Answers1

1

You can't have an into in the middle of a cursor statement; it's that which is throwing the exception. If your o_list CTE was only selecting a single value then this would run, but v_asn_count would still be null afterwards. With multiple columns selected in o_list it gets the ORA-00947. (This is possibly a parser bug; arguably it should either error just because there is an into clause, or use the select list from the correct CTE query).

It isn't really clear if you need the cursor at all and are trying to reduce code duplication, but it looks like you really just want to do:

SELECT COUNT(DISTINCT ASN_NO)
INTO V_ASN_COUNT
FROM AN_ORDER_INFO OI, AN_SHIPMENT_INFO SI
-- where bunch of stuff
;

IF(V_ASN_COUNT > 1) THEN
  RAISE MULTIPLE_ASNS;
END IF;

(Your where bunch of stuff presumably includes the join conditions; it's off-topic but you might want to think about using ANSI join syntax).

If you have an existing cursor and you want to count the distinct values separately from (and before) actually consuming the cursor you could open it, iterate over it to examine the asn_no values, and then raise an exception if needed; and then for the actual consumption close and reopen the cursor. But that would still execute the cursor query twice.

Or if your processing, particularly the fetch, can accommodate it, you could add an analytic count to the existing cursor query:

COUNT(DISTINCT dummy) OVER (PARTITION BY NULL) AS ASN_COUNT

... which would give you the number of distinct asn_no values across the entire result set as an extra column on every row of that result set. You could then check that number after your first fetch before doing anything else, and raise the exception at that point.

That isn't going to work if you have to count in this procedure but return the cursor to another procedure/caller; the caller would have to check the results and raise the exception, which probably isn't how you see this working.

Alex Poole
  • 183,384
  • 11
  • 179
  • 318
  • Thanks Alex, I'm returning the cursor from a stored procedure. The "o_list" has what im returning if i don't run into a case where multiple vendors send the same ASN number. I would have to perform that query twice, once to count, and once to get my list then. And therefore it sounds like opening my cursor would be more efficient in that case, but having trouble with syntax and finding the right resource example. – SomeRandomDeveloper Oct 15 '14 at 16:13
  • 1
    It wouldn't necessarily be more efficient, but would reduce code duplication, and thus maintenance - and the risk that one query is changed and the other missed. – Alex Poole Oct 15 '14 at 16:17
  • That's exactly what i was thinking too. I updated my question with my current cursor opening stumblings since that seems to be the real issue at hand now. Perhaps i should change the title of this question to be more appropriate. – SomeRandomDeveloper Oct 15 '14 at 16:25
  • Maybe it would be easier adding the count to the main query over a partition like you suggested, going to try that. – SomeRandomDeveloper Oct 15 '14 at 16:29
  • 1
    I think this answers the actual question i asked about my error. How to acheive this with a cursor is a different question i posted here: http://stackoverflow.com/questions/26388104/oracle-how-to-open-cursor-and-select-one-column-of-many-into-a-variable – SomeRandomDeveloper Oct 15 '14 at 17:14
  • I'd started to update this answer with some code, but you're absolutely right to make it a new question. I've posted my code there instead *8-) – Alex Poole Oct 15 '14 at 17:24