TLDR; Is there anything I can set in an Oracle Form that would let me bind a placeholder to a Data Block's ORDER BY Clause?
I'm developing a form using Oracle Form Builder 10.1.2.3.0 (because it's interfacing with a system that makes other form types undesirable).
It has a Data Block with Query Data Source Type = Table.
Its WHERE Clause allows the user to be flexible in the search, producing rows of varying interest. I want rows with a perfect match to appear before those that are not.
To implement this specification, I wrote the form's WHERE Clause and ORDER BY Clause to reflect this SQL*Plus example:
var sf varchar2(30)
exec :sf := 'X'
with mdual as (
select case when level=1 then dummy else dummy || level end dummy
from dual
connect by level <= 2
)
select *
from mdual
where :sf is null or dummy like '%' || upper(:sf) || '%'
order by case when :sf = dummy then 0 else 1 end asc, dummy;
The form variable reference is not as simple as :sf and the WHERE Clause is a bit more complicated as is the ORDER BY Clause but this type of query is valid. When executed in SQL*Plus, it produces exactly the type of result I desire. You can reverse the first sort expression to prove it.
When I execute the form, I get an ORA-1008 until I comment the first ORDER BY expression.
My conclusion is that Oracle Forms binds placeholder references in a WHERE Clause but not an ORDER BY Clause.
I could experiment with setting the Query Data Source Type to Procedure and pass the procedure the filter field but a view has more utility than a procedure and so I'd prefer to keep using the view that I've defined for the Query Data Source Type.
Is there a way I can coerce Oracle Forms to do what I consider the right thing?
You can use SET_BLOCK_PROPERTY built-in function in order to make it dynamical and depending on a local or bind variable such as
DECLARE
v_orderby := ' CASE WHEN '||:sf||' = ''dummy'' THEN 0 ELSE 1 END, dummy';
BEGIN
SET_BLOCK_PROPERTY('block1',ORDER_BY, v_orderby);
EXECUTE_QUERY;
END;
which might be invoked from a trigger such as WHEN-NEW-BLOCK-INSTANCE after sending cursor to this block by using another action such as clicking on a button or pressing a key such as enter etc.