Question

I've come across a strange behavior that I can't diagnose.

I've got an Oracle Database (11g) and I've built a view within this database. This view returns a list of information which was fine before the issue and is currently fine after the issue.

Let's say that this view returns 10 rows. When I run an aggregate function over this view, e.g. lets say a COUNT(*) I get a list of 10 rows each displaying 'Null' instead of one row with the number 10.

This was an issue that started abruptly without me knowingly making changes to the database or the view (however this is a big corporate database and changes could have been made, by a select few other people - all of which are currently denying any changes were made) There are also no know triggers that effect the view

This issue does not appear in other tables or other views. I've tried running an aggregate function on each table or view that makes up the final view and each of those returns a single number as expected.

I'm not sure what else to try. My Google searches are not offering any leads either. I would upload the code, but it is large and unwieldy, I also couldn't begin to explain how it was looking at data (suffice it to say that the database is French built)

What is really getting me is the fact that the view returns the data as expect but when I run an aggregate function over it (e.g. SELECT COUNT(*) FROM VIEW_THAT_IS_FAILING) it fails in this weird way. Any ideas?

View that is failing definition:

SELECT x.OBJEXCDE,
       x.OBJDSC,
       x.CLASSIFICATION,
       x.COUNTRY,
       NVL(y.MONTH_USAGE, 0) AS MONTH_USAGE,
       x.STKQTY,
       x.STANDARD_COST

    FROM (SELECT a.OBJINCDE, a.OBJEXCDE, a.OBJDSC, NVL(b.STKQTY, 0) AS STKQTY, NVL(c.OBJPRC1VAL, 0) AS STANDARD_COST, NVL(d.OBJCHARVAL, 'Exception') AS CLASSIFICATION,
                 CASE WHEN TO_CHAR(b.STOREINCDE, '0000') || TO_CHAR(c.OBJRTEINCDE, '000') =  ' 0615 130' THEN 'UK'
                      ELSE 'IRE' END AS COUNTRY             
             FROM P_OBJ a, P_OBJSTORE b, P_OBJPRC c,
                  (SELECT a.OBJINCDE, b.OBJCHARVAL
                      FROM P_OBJ a, (SELECT OBJINCDE, OBJCHARVAL FROM P_OBJCHAR WHERE CHARINCDE = 524) b
                      WHERE a.OBJINCDE = b.OBJINCDE (+)) d             
             WHERE a.OBJINCDE = b.OBJINCDE (+)
             AND a.OBJINCDE = c.OBJINCDE (+)
             AND a.OBJINCDE = d.OBJINCDE (+)
             AND TO_CHAR(b.STOREINCDE, '0000') || TO_CHAR(c.OBJRTEINCDE, '000') IN (' 0615 130', ' 1158 284')
             AND a.CLASSINCDE IN (83, 84, 126)  --New Parts, Repairable Parts, Installation Parts
             AND (d.OBJCHARVAL IS NULL OR NVL(c.OBJPRC1VAL, 0) = 0)) x,
         W_USAGE_1_MONTH y

    WHERE x.OBJINCDE = y.OBJINCDE (+)
    AND x.COUNTRY = y.COUNTRY (+)

    AND (NVL(y.MONTH_USAGE, 0) + x.STKQTY) > 0

Definition for W_USAGE_1_MONTH:

SELECT a.OBJINCDE, 
       a.OBJEXCDE, 
       a.OBJDSC, 
       NVL(b.STKQTY, 0) AS STKQTY, 
       NVL(c.OBJPRC1VAL, 0) AS STANDARD_COST, 
       NVL(d.OBJCHARVAL, 'Exception') AS CLASSIFICATION,
       CASE WHEN TO_CHAR(b.STOREINCDE, '0000') || TO_CHAR(c.OBJRTEINCDE, '000') =  ' 0615 130' THEN 'UK' ELSE 'IRE' END AS COUNTRY             

    FROM P_OBJ a, 
         P_OBJSTORE b, 
         P_OBJPRC c,
         (SELECT a.OBJINCDE, b.OBJCHARVAL FROM P_OBJ a, (SELECT OBJINCDE, OBJCHARVAL FROM P_OBJCHAR WHERE CHARINCDE = 524) b WHERE a.OBJINCDE = b.OBJINCDE (+)) d             

    WHERE a.OBJINCDE = b.OBJINCDE (+)
    AND a.OBJINCDE = c.OBJINCDE (+)
    AND a.OBJINCDE = d.OBJINCDE (+)
    AND TO_CHAR(b.STOREINCDE, '0000') || TO_CHAR(c.OBJRTEINCDE, '000') IN (' 0615 130', ' 1158 284')
    AND a.CLASSINCDE IN (83, 84, 126)  --New Parts, Repairable Parts, Installation Parts
    AND (d.OBJCHARVAL IS NULL OR NVL(c.OBJPRC1VAL, 0) = 0)
Was it helpful?

Solution 2

While the support request still hasn't been responded to, I had a crack at figuring out this problem.

While breaking the view back to it's essentials I found that when when I was attempting to make a aggregation of a smaller aggregate part the SQL was failing. So the aggregation in W_USAGE_1_MONTH was causing the aggregation of the larger few to fail in a way that would out put a series of NULL values to the count of how many rows, instead of one line with the number of counted rows.

While I did a bunch of tinkering with the view what appears to have fixed the behavior was when I encapsulated the W_USAGE_1_MONTH in a FROM Clause Select statement:

(SELECT OBJINCDE, MONTH_USAGE, COUNTRY FROM W_USAGE_1_MONTH) b

My feeling is that the DBA (whom I don't have immediate access to) made a change that had an effect on the order of processing SQL statements. Forcing the the W_USAGE_1_MONTH view to be evaluated before it is used by the statement results in the operation successfully completing.

Not a very exciting end to a strange occurrence and an answer that doesn't explain the underlying cause as I don't know what changes could have been made that effect evaluation order of statements. However perhaps this would help someone else to look at evaluation order for weird behavior.

OTHER TIPS

Just for fun, try the following:

SELECT x.OBJEXCDE,
       x.OBJDSC,
       x.CLASSIFICATION,
       x.COUNTRY,
       NVL(y.MONTH_USAGE, 0) AS MONTH_USAGE,
       x.STKQTY,
       x.STANDARD_COST
  FROM (SELECT a.OBJINCDE,
               a.OBJEXCDE,
               a.OBJDSC,
               NVL(b.STKQTY, 0) AS STKQTY,
               NVL(c.OBJPRC1VAL, 0) AS STANDARD_COST,
               NVL(d.OBJCHARVAL, 'Exception') AS CLASSIFICATION,
               CASE
                 WHEN TO_CHAR(b.STOREINCDE, '0000') || TO_CHAR(c.OBJRTEINCDE, '000') =  ' 0615 130' THEN 'UK'
                 ELSE 'IRE'
               END AS COUNTRY             
           FROM P_OBJ a
           LEFT OUTER JOIN P_OBJSTORE b
             ON (a.OBJINCDE = b.OBJINCDE)
           LEFT OUTER JOIN P_OBJPRC c
             ON (a.OBJINCDE = c.OBJINCDE)
           LEFT OUTER JOIN (SELECT a.OBJINCDE, b.OBJCHARVAL
                              FROM P_OBJ a
                              LEFT OUTER JOIN (SELECT OBJINCDE, OBJCHARVAL
                                                 FROM P_OBJCHAR
                                                 WHERE CHARINCDE = 524) b
                                ON (a.OBJINCDE = b.OBJINCDE)) d
             ON (a.OBJINCDE = d.OBJINCDE)
          WHERE TO_CHAR(b.STOREINCDE, '0000') || TO_CHAR(c.OBJRTEINCDE, '000') IN (' 0615 130', ' 1158 284') AND
                a.CLASSINCDE IN (83, 84, 126) AND --New Parts, Repairable Parts, Installation Parts
                (d.OBJCHARVAL IS NULL OR
                NVL(c.OBJPRC1VAL, 0) = 0)) x
  LEFT OUTER JOIN W_USAGE_1_MONTH y
    ON (x.OBJINCDE = y.OBJINCDE AND
        x.COUNTRY = y.COUNTRY)
  WHERE (NVL(y.MONTH_USAGE, 0) + x.STKQTY) > 0

which is just the original view reworked to use ANSI join syntax. Give it a try and see if it changes anything.

It could also be that the DBA's applied a patch or made some other change which is affecting this.

Share and enjoy.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top