1

I have a PL/SQL procedure with multiple parameters. When a webapp calls the procedure, if it's not using a certain parameter, it passes is as null, ie

procedure test (param1 in varchar2, param2 in varchar2, param3 in varchar2, cursor out sys_refcursor)
...
end procedure test;

I want to make an SQL query where I include the given parameters in the WHERE clause only if the parameter is not null. Is there a way to achieve this in an elegant way, other than building the SQL query in a string and then opening the cursor for that string, like this

vSQL := 'SELECT * from TABLE WHERE something = something_else';
if param1 IS NOT NULL
    vSQL := vSQL || 'AND some_param = ' || param1;
2
  • Similar Question Commented Feb 8, 2011 at 11:10
  • I want to point out that if the parameters are ever exposed to users, this is a classic example of code that has a high risk of SQL*Injection. So you should use DBMS_ASSERT to check your final SQL for good behavior. Commented Feb 8, 2011 at 17:24

3 Answers 3

1

I have answered a similar question on dba.stackexchange.com

Sign up to request clarification or add additional context in comments.

Comments

1

You can code it all into a single select

SELECT * from TABLE WHERE something = something_else
AND ((param1 IS NOT NULL AND some_param = param1) OR 1)

1 Comment

This answer is a nice simple solution when calling named queries from within code where PL typically isn't an option. I like this for times when building criteria queries or piecing together where clauses is overkill.
0

Create a test table:

create table testtab
(
name_first varchar2(50),
name_last varchar2(50),
name_middle varchar2(50)
);

insert into testtab values ('Joe', 'Jones', 'A');
insert into testtab values ('Joe', 'Smith', 'A');
insert into testtab values ('Steve', 'Jones', 'B');
insert into testtab values ('Axl', 'Rose', 'C');
insert into testtab values ('Phil', 'McCracken', 'D');
commit;

Create your procedure:

CREATE OR REPLACE procedure ECDATA.get_testtab_rows
(i_name_first in varchar2 default null,
i_name_last in varchar2 default null,
i_name_middle in varchar2 default null,
o_cursor out sys_refcursor
) as

    v_result_cur    sys_refcursor;

begin

    open v_result_cur for
        select * from testtab
        where name_first like nvl(i_name_first, '%')
        and name_last like nvl(i_name_last, '%')
        and name_middle like nvl(i_name_middle, '%')
    ;

    o_cursor := v_result_cur;

end;
/

Then call it like this:

declare

    v_cur sys_refcursor;
    testtab_rec testtab%rowtype;

begin

    get_testtab_rows(i_name_last=>'Jones', o_cursor=>v_cur);
    loop

        fetch v_cur into testtab_rec;
        exit when v_cur%notfound;
        dbms_output.put_line(testtab_rec.name_first || ' ' || testtab_rec.name_middle || ' ' || testtab_rec.name_last);

    end loop;

exception
    when others then raise;
end;

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.