I would like to write a stored procedure like this:
CREATE OR REPLACE FUNCTION my_function(param_1 text, param_2 text DEFAULT NULL::text) RETURNS bigint AS
$$
DECLARE ret bigint;
BEGIN
INSERT INTO my_table(val_1, val_2) VALUES (param_1, param_2);
-- do some more stuff
RETURN ret;
END;
$$
LANGUAGE plpgsql;
However, I would like to use val_2
column's DEFAULT
value instead of NULL
- if NULL
is provided as the param_2
value.
Something like this:
INSERT INTO my_table(val_1, val_2) VALUES (param_1, COALESCE(param_2, DEFAULT));
is obviously wrong, since the INSERT
statement specification explicitly states an expression OR DEFAULT
can be used, DEFAULT
itself is not available in expressions.
I found two solutions myself but I'm not satisfied with them.
- Select the
DEFAULT
value from the information schema and use it in theCOALESCE
expression.
I'm no expert but it seems like there should be a simpler and more elegant way to do it.
- Use
INSERT
and thenUPDATE
Like this:
-- ...
INSERT INTO my_table(val_1) VALUES (param_1)
RETURNING id INTO id_var;
IF (param_2) IS NOT NULL THEN
UPDATE my_table SET val_2 = param_2 WHERE id = id_var;
END IF;
-- ...
There is however a catch in this solution. The actual table of the production system has some intricate triggers which run on UPDATE
statements on this table so I would generally like to avoid using updates if possible.
Generally, I'll possibly stick to the second solution but that would possibly require adding some hacks to the aforementioned triggers. But if there is a way to avoid this - I will be very grateful for pointing it out.
Using dynamic-SQL:
SqlFiddleDemo
This is a bit long for a comment.
One method would be to declare the column
NOT NULL
. Inserting theNULL
value would generate a constraint violation, which you can catch in theinsert
usingon constraint
.This seems like a correct approach. If the column has a default value, then you probably do not want it to be
NULL
.If insert is as simple as in the question, I'd use two different
INSERT
statements, since the resulting code is small and readable and fast:For inserts with a greater level of complexity, for example with more than one optional parameter is used, I may opt for the dynamic-SQL solution by @lad2025 above.
As
param_2
can only be one ofnull
ornot null
only one of the selects will return a row to be inserted:If it is necessary to return the inserted values: