ad-hoc PL/SQL doesn't do it
Vladimir Andreev, May 03, 2004 - 2:04 pm UTC
Hi Tom,
Thanks for your answer. It seems I have trouble explaining my problems with this. Another try:
I have some SQL statements that check for things like redundant indexes, indexes that include a unique key but are not declared unique, and such. Each of these is a single SQL statement... I'd like to keep it that way and still cover all cases. I can't use an ad-hoc PL/SQL function, as they are not allowed in SQL. IOW, this doesn't work:
19:06:48 sys@flado>declare
19:07:05 2 function Get_Lob return varchar2 is
19:07:05 3 begin return 'example'; end;
19:07:05 4 begin
19:07:05 5 for i in (select Get_Lob d from dual) loop
19:07:05 6 dbms_output.put_line(i.d);
19:07:05 7 end loop;
19:07:05 8 end;
19:07:05 9 /
for i in (select Get_Lob d from dual) loop
*
ERROR at line 5:
ORA-06550: line 5, column 19:
PLS-00231: function 'GET_LOB' may not be used in SQL
Second, I don't want to take the function-based indexes in account, exactly for the reasons you gave: an index on f(x) is not the same as an index on x. However, a descending index on X is (for the above mentioned purposes) the same as an ascending index on X:
sys@flado>create table t(x int, y int);
Table created.
sys@flado>create index t_asc on t(x);
Index created.
sys@flado>create index t_desc on t(x desc);
Index created.
sys@flado>col column_name for a13
sys@flado>col index_name for a7
sys@flado>select index_name,column_position,column_name,descend from dba_ind_columns
2 where table_name='T';
INDEX_N COLUMN_POSITION COLUMN_NAME DESC
------- --------------- ------------- ----
T_ASC 1 X ASC
T_DESC 1 SYS_NC00003$ DESC
2 rows selected.
For all intents and purposes, these two indexes are identical -- with Oracle, one can range-scan B*Tree indexes in any direction, so one of these two is redundant. But how do you tell that these two indexes in fact index the same column? Or more generally, how do I find out that there is in fact an index on t(x)?
Here the dba_ind_expressions view comes into play:
sys@flado>set long 10
sys@flado>select index_name,column_position,column_expression
2 from dba_ind_expressions
3 where table_name='T';
INDEX_N COLUMN_POSITION COLUMN_EXP
------- --------------- ----------
T_DESC 1 "X"
1 row selected.
So, theoretically, I could do a (inline) view that would provide the same information as dba_ind_columns, only replacing the descending column names (SYS_NC00003$ and the like) with the real names -- and parsing this "function" is not at all hard. Then I could adjust my SQLs to cover all cases...
Only in theory, since I cannot get the column expression out of the dictionary *and* pass it to the SQL engine without the help of a *stored* function (packaged or not). Let's see... maybe Oracle provides such a (simple, really) function in one of its many supplied packages?
Nope.
And that's where I'm stuck. I'm quite sure there isn't any solution to this, but I was sure that solutions to other problems didn't exist until I found them on your site :-)
If you can pull a solution to this problem out of your hat (or sleeve?), I would be extremely impressed - not to mention grateful.
Regards,
Flado
May 03, 2004 - 7:45 pm UTC
but in general
t(x desc,y,z)
t(x,y desc,z)
are not "the same" at all -- seems like might be looking for a "so rare, it won't happen" case.
without a user defined function, you will not be "whereing" on a long.
My comment about anonymous blocks was -- you can write code to do this, but not sql.
varchar2's are limited to 4000 bytes in sql.
clobs are different beasts from longs (it is not "simple, really", it is actualy quite "large" and hard)
(on a *production* system, I wouldn't let you look for duplicate indexes in the first place. that is something for TEST or DEV, not production)
sorry, no magic on this one.