views:

802

answers:

2

Suppose I have a PL/SQL stored procedure as follows:

PROCEDURE do_something(foo VARCHAR2 DEFAULT NULL) IS
BEGIN
    /* Do something */
END;

Now, suppose do_something is invoked two different ways:

/* Scenario 1: The 'foo' parameter defaults to NULL */
do_something();

/* Scenario 2: The 'foo' parameter is explicitly set to NULL */
do_something(foo => NULL)

How can I define the do_something procedure to determine which scenario is calling it?

Edit: Clarifying my intentions for this procedure:

FUNCTION find_customer(name VARCHAR2 DEFAULT NULL, number VARCHAR2 DEFAULT NULL) RETURN NUMBER IS
BEGIN
    /* Query the "customer" table using only those parameters provided */
END;

Below are example uses of this procedure with the associated SQL clauses desired:

/* SELECT * FROM customer WHERE customer.name = 'Sam' */
find_customer(name => 'Sam')

/* SELECT * FROM customer WHERE customer.name = 'Sam' AND customer.number = '1588Z' */
find_customer(name => 'Sam', number => '1588Z')

/* SELECT * FROM customer WHERE customer.name = 'Sam' AND customer.number IS NULL */
find_customer(name => 'Sam', number => NULL)

/* SELECT * FROM customer WHERE customer.name IS NULL */
find_customer(name => NULL)

/* SELECT * FROM customer WHERE customer.name IS NULL AND customer.number IS NULL */
find_customer(name => NULL, number => NULL)
+6  A: 

You could overload the procedure instead of using a default value:

PROCEDURE do_something(foo VARCHAR2) IS
BEGIN
    /* Do something */
END;

PROCEDURE do_something IS
BEGIN
    /* here you know: no argument. Then call do_something(null) */
END;
Stefan Steinegger
+1 Very clear and effective! Unfortunately, I didn't make myself completely clear. I am writing a procedure with several parameters, many of which can be defaulted. Overloading would require many permutations that I would rather avoid. However, considering you perfectly answered the question I asked, I think you deserve the accepted answer.
Adam Paynter
You shouldn't bother about the many procedures. I didn't work with PL/SQL for years, so I forgot if you can make them private or not. If you can, it will not be an issue at all. Just make sure that you don't have duplicated code. Call one procedure from the other. You could eve write a third (private?) procedure containing the logic and having additional arguments that is called from the "public" procedures.
Stefan Steinegger
You can't have private procedures per se but you can have private procedures within a Package.
Jeffrey Kemp
+6  A: 

How about instead of defaulting to null, default the omitted parameter values to something you will never use in the real world? The values you use should belong to some domain so choose values outside that domain.

eg

PROCEDURE do_something(foo VARCHAR2 DEFAULT '*#@') IS

l_foo  VARCHAR2(32000); -- local copy of foo parm

BEGIN

IF foo = '*#@' THEN

-- I know the parm was omitted

   l_foo := NULL;

ELSE

   l_foo := foo;

END IF;

END;

Greg
This was my idea as well. The true defaults can be implemented in the procedure body.
Mr. Shiny and New
Ditto, but I'd actually use unprintable characters. Generally chr(7) [which is the ASCII code for beep sound].
Gary
Ditto ditto! I like this option too, especially Gary's comment about unprintable characters.
Adam Paynter