I am trying to create a report of INVALID objects in Oracle. The requirement is to print a custom message when no rows are returned (This is because the output will be redirected to an HTML report). I tried the following query:
(select count(*), owner,object_type,to_char( LAST_DDL_TIME, 'DD-MM-YYYY HH24:MI:SS' ) as last_ddl_time from dba_objects where status='INVALID' and trunc(last_ddl_time) = sysdate -1 group by owner,object_type , LAST_DDL_TIME order by object_type) UNION (select '** DDL Changes in the last 24 hours' text from dual);
Error am seeing:
ORA-00907: missing right parenthesis
While the individual queries work without an issue, it fails to execute when a UNION is introduced. How can I fix this?
Advertisement
Answer
It can’t work that way. If you’re using UNION, SELECT statements have to return the same number of columns which match in datatype.
This is an invalid procedure (created in my SYS schema for simplicity; don’t do that yourself):
SQL> create or replace procedure p_test 2 is 3 begin 4 end; 5 / Warning: Procedure created with compilation errors.
Query you’d run; notice NOT EXISTS in the second query – it’ll prevent the message to be displayed if there are some invalid objects. Also, I modified date condition to “today” (subtracted 0) as I can’t wait until tomorrow to post it.
SQL> select
2 count(*),
3 owner,
4 object_type,
5 to_char(LAST_DDL_TIME, 'DD-MM-YYYY HH24:MI:SS') as last_ddl_time
6 from dba_objects
7 where status = 'INVALID'
8 and trunc(last_ddl_time) = trunc(sysdate) - 0
9 group by owner,
10 object_type,
11 LAST_DDL_TIME
12 UNION
13 select
14 0,
15 null,
16 'DDL Changes in the last 24 hours',
17 to_char(sysdate, 'dd-mm-yyyy')
18 from dual
19 where not exists (select null
20 from dba_objects
21 where status = 'INVALID'
22 and trunc(last_ddl_time) = trunc(sysdate) - 0
23 )
24 order by object_type;
COUNT(*) OWNER OBJECT_TYPE LAST_DDL_TIME
---------- ---------- -------------------------------- -------------------
1 SYS PROCEDURE 04-04-2021 12:36:07
SQL>
If I drop the invalid procedure:
SQL> drop procedure p_test;
Procedure dropped.
SQL> select
2 count(*),
3 owner,
4 object_type,
5 to_char(LAST_DDL_TIME, 'DD-MM-YYYY HH24:MI:SS') as last_ddl_time
6 from dba_objects
7 where status = 'INVALID'
8 and trunc(last_ddl_time) = trunc(sysdate) - 0
9 group by owner,
10 object_type,
11 LAST_DDL_TIME
12 UNION
13 select
14 0,
15 null,
16 'DDL Changes in the last 24 hours',
17 to_char(sysdate, 'dd-mm-yyyy')
18 from dual
19 where not exists (select null
20 from dba_objects
21 where status = 'INVALID'
22 and trunc(last_ddl_time) = trunc(sysdate) - 0
23 )
24 order by object_type;
COUNT(*) OWNER OBJECT_TYPE LAST_DDL_TIME
---------- ---------- -------------------------------- -------------------
0 DDL Changes in the last 24 hours 04-04-2021
SQL>