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\'
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:
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.
name
has no default, since it is required at all times.WARNING
is raised and nothing else happens.UPDATE
will only change columns for given parameters.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.
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.