Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Functions with variable number of input parameters

I'm creating a stored procedure (function) in a PostgreSQL DB, which updates a table depending on its input. In order to create a variable number of parameter function, I'm creating an extra input parameter called mode, which I use to control which parameters I use on the update query.

CREATE OR REPLACE FUNCTION update_site(
    mode integer,
    name character varying,
    city character varying,
    telephone integer,
)
RETURNS integer AS
$$
BEGIN
IF mode = 0 THEN
BEGIN
    UPDATE "Sites" SET 
    ("City","Telephone") = (city,telephone)
    WHERE "SiteName" = name;
    RETURN 1;
    EXCEPTION WHEN others THEN
    RAISE NOTICE 'Error on site update: %, %',SQLERRM,SQLSTATE;
    RETURN 0;
END;
ELSIF mode = 1 THEN
BEGIN
    UPDATE "Sites" SET "City" = city
    WHERE "SiteName" = name;
    RETURN 1;
    EXCEPTION WHEN others THEN
    RAISE NOTICE 'Error on site update: %, %',SQLERRM,SQLSTATE;
    RETURN 0;
END;
    ELSIF mode = 2 THEN
BEGIN
    UPDATE "Sites" SET "Telephone" = telephone
    WHERE "SiteName" = name;
    RETURN 1;
    EXCEPTION WHEN others THEN
    RAISE NOTICE 'Error on site update: %, %',SQLERRM,SQLSTATE;
    RETURN 0;
END;
    ELSE
            RAISE NOTICE 'Error on site update: %, %',SQLERRM,SQLSTATE;
    RETURN 0;
    END IF;
END;
$$ LANGUAGE plpgsql;

What would be best? To create a function update_site(<all the columns of table>) and a separate function update_site(id integer, <varchar column to update>), or use the mode in one function to define the difference? Which option is more efficient? One unique function or different ones for each purpose?

like image 873
anairinac Avatar asked May 28 '13 00:05

anairinac


People also ask

Can a function have variable number of parameters?

To call a function with a variable number of arguments, simply specify any number of arguments in the function call. An example is the printf function from the C run-time library. The function call must include one argument for each type name declared in the parameter list or the list of argument types.

Which functions used for variable parameters?

Variadic functions are functions that can take a variable number of arguments.

Can a function have variable number of parameters in Python?

Yes. You can use *args as a non-keyword argument. You will then be able to pass any number of arguments. As you can see, Python will unpack the arguments as a single tuple with all the arguments.

Can a function have variable number of parameters justify?

You can define your own methods with variable parameters, and you can specify any type for the parameters, even a primitive type. Here is a simple example: a function that computes the maximum of a variable number of values. Simply call the function like this: double m = max(3.1, 40.4, -5);


2 Answers

Advanced features like VARIADIC or even polymorphic input types and dynamic SQL are very powerful. The last chapter in this answer provides an advanced example:

  • Refactor a PL/pgSQL function to return the output of various SELECT queries

But for a simple case like yours, you can just use default values for function parameters. It all depends on exact requirements.
If the columns in question are all defined NOT NULL, this would probably be simpler and faster:

CREATE OR REPLACE FUNCTION update_site(_name      text    -- always required
                                     , _city      text    DEFAULT NULL
                                     , _telephone integer DEFAULT NULL)
  RETURNS integer AS
$func$
BEGIN
   IF _city IS NULL AND _telephone IS NULL THEN
      RAISE WARNING 'At least one value to update required!';
      RETURN;  -- nothing to update
   END IF;

   UPDATE "Sites"
   SET    "City"      = COALESCE(_city, "City")
        , "Telephone" = COALESCE(_telephone, "Telephone")
   WHERE  "SiteName"  = _name;
END
$func$  LANGUAGE plpgsql;

Read about default values in the manual!

To avoid naming conflicts between parameters and column names I make it a habit to prefix input parameters with _. That's a matter of taste and style.

  • The first parameter name has no default, since it is required at all times.
  • Other parameters can be omitted.
  • At least one is required, or a WARNING is raised and nothing else happens.
  • The UPDATE will only change columns for given parameters.
  • Can easily be expanded for N parameters.

Function call

Since Postgres 9.5:

The simple way is with positional notation for parameters. This only allows to omit the rightmost parameter(s):

SELECT update_site('foo', 'New York');  -- no telephone

Named notation allows to omit any parameter that has a default value:

SELECT update_site(name => 'foo', _telephone => 123);  -- no city

Both can be combined in mixed notation:

SELECT update_site('foo', _telephone => 123);  -- still no city

In Postgres 9.4 or older, := was used for assignment in the call:

SELECT update_site(name := 'foo', _telephone := 123);
SELECT update_site('foo', _telephone := 123);

Still valid in Postgres 12 for backward compatibility, but rather use the modern notation.

like image 187
Erwin Brandstetter Avatar answered Oct 21 '22 09:10

Erwin Brandstetter


There are a few things you'll want to look into:

  • Dynamically building the SQL using the format function and its %I and %L specifiers, then executing it with EXECUTE ... USING; and

  • Using VARIADIC parameters to take variable numbers of arguments to the function, with the caveat that they must all be the same data type.

like image 4
Craig Ringer Avatar answered Oct 21 '22 09:10

Craig Ringer