Question

I have two tables 'survey' & 'survey_processed' and both are basically similar tables. I have a working query which uses UNION ALL operator between two tables & am getting some counts. When I try to translate it in to a Materialized View, I get the error related to ON COMMIT. Check out the MV DDL & Error below.

    CREATE MATERIALIZED VIEW vwm_survey_records_count
    REFRESH FAST ON COMMIT
    AS
    SELECT
        survey_combined.survey_header_id,
        COUNT(*) AS count_total,
        COUNT(CASE WHEN survey_combined.processed_flag = 'Y' THEN 1 ELSE NULL END) AS count_a,
        COUNT(CASE WHEN survey_combined.approved_flag IS NULL THEN 1 ELSE NULL END) AS count_b,
        COUNT(CASE WHEN survey_combined.processed_flag = 'N' AND survey_combined.approved_flag = 'Y' THEN 1 ELSE NULL END) AS count_c,
        COUNT(CASE WHEN survey_combined.approved_flag = 'N' THEN 1 ELSE NULL END) AS count_d
    FROM 
    (
    SELECT survey_header_id, 'N' AS processed_flag, approved_flag FROM survey
    UNION ALL
    SELECT survey_header_id, 'Y' AS processed_flag, approved_flag FROM survey_processed) survey_combined
    INNER JOIN survey_header ON survey_combined.survey_header_id = survey_header.id
    GROUP BY survey_combined.survey_header_id;

Error I get if i run the above command:
'SQL Error: ORA-12054: cannot set the ON COMMIT refresh attribute for the materialized view' .

But, if i use the 'REFRESH COMPLETE ON DEMAND' it works. I know am obviously breaking some restrictions for the ON COMMIT attribute, but can't figure out which. Can someone let me know what am doing wrong on the above query? Also, Is there any better approach for the query as such to make it efficient & work with 'REFRESH FAST ON COMMIT', while creating the MV.

Note: I have the MV Log created for both the tables using rowid on the selected columns.
Let me know if someone has any questions.

Thanks in advance.

Here's the DDL for MV Log as requested by 'jonearles'

    CREATE MATERIALIZED VIEW LOG ON survey WITH SEQUENCE,ROWID (id, survey_header_id, approved_flag, processed_flag) INCLUDING NEW VALUES;
    CREATE MATERIALIZED VIEW LOG ON survey_processed WITH SEQUENCE,ROWID (id, survey_header_id, approved_flag) INCLUDING NEW VALUES;
    CREATE MATERIALIZED VIEW LOG ON survey_header WITH SEQUENCE,ROWID (id) INCLUDING NEW VALUES;

Note: The column 'processed_flag' in the 'survey' table will be dropped later on. Technically, the two tables were recently split based on the value of the 'processed_flag' column. So, the 'survey' table has all the un-processed records (processed_flag = 'N') & 'survey_processed' has the processed records (processed_flag = 'Y'). After the split, the column is irrelevant.

Was it helpful?

Solution

I think you're out of luck here. From Restrictions on Fast Refresh on Materialized Views with UNION ALL:

The defining query must have the UNION ALL operator at the top level.

And replacing the UNION ALL with outer joins doesn't work either. Aggregation and outer joins don't appear to work together. The code below is not equivalent to yours, but it demonstrates that even a much simplified version of your query won't work:

CREATE MATERIALIZED VIEW vwm_survey_records_count
REFRESH COMPLETE ON DEMAND AS
SELECT survey_header.id AS survey_header_id, COUNT(*) AS count_total
FROM survey_header, survey, survey_processed
WHERE survey_header.id = survey.survey_header_id(+)
GROUP BY survey_header.id;


delete from MV_CAPABILITIES_TABLE;
begin
    DBMS_MVIEW.EXPLAIN_MVIEW ('VWM_SURVEY_RECORDS_COUNT');
end;
/
select possible, msgno, msgtxt
from MV_CAPABILITIES_TABLE
where capability_name = 'REFRESH_FAST_AFTER_INSERT';

POSSIBLE    MSGNO   MSGTXT
--------    -----   ------
N           2048    outer join in mv
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top