I have a stored procedure that takes optional parameters from a Json structure. If the json values is provided, the parameters will be used as a conditions for the cursors. If json value is not provided I don't want that condition. I have solved this by using Coalesce/Nvl in the sql condition. The problem is that the procedure is running for a very long time using Nvl/Coalesce. Is there a different method I can use which is more efficent? Perhaps dynamic sql?
My procedure:
Create or Replace Procedure findaccounts
(jsonIn IN clob,
jsonOut OUT varchar2)
As
obj json := json(jsonIn);
json_obj_out json;
json_lst json_list := json_list();
--Getstring is a function that sets variable to null if json value is not found
istatus varchar2(10) := GetString(obj json, 'status');
icreatedate := GetString(obj json, 'daysold');
iage int := GetString(obj json, 'age');
irownum int := GetString(obj json, 'rownum');
Begin
For rec in (Select A.accountnumber
From Accounts A
Inner Join Accountowner Ao On A.ownerId = Ao.Id
Where A.Status = iStatus
And A.daysold >= Coalesce(idaysold,A.daysold)
And Ao.Age = Coalesce(iAge,Ao.Age)
And rownum <= Coalesce(iRownum,5))
loop
obj := json();
obj.put('accountnumber',Rec.accountnumber);
json_lst.append(obj.to_json_value);
end loop;
json_lst.print;
jsonOut := json_lst.to_char();
End;
resolved:
Performance boosted with dynamic sql. The option to have dynamic bind variables was resolved via dbms_sql package as execute immediate does not have this option.
Functionally,
Coalesceis a great way to handle optional search criteria. Performancewise it is not good. The optimiser will not be able to optimize efficiently since it decides on the execution plan only once, optimising for the search criteria provided the first time the SQL is run.If different executions plans would be required to get acceptable performance then you need to use different SQL statements for those different search patterns.
Here are two different solutions that I have used in the past:
Create several different SQL:s where each handles a subset of the possible search criteria that will share the same execution plan. In your case you could have one you use when
iAgeisnull, another whenidaysoldisnulland a third when neither isnull.Use dynamic SQL.