【发布时间】:2016-06-26 16:18:03
【问题描述】:
我想写一个这样的存储过程:
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;
但是,我想使用val_2 列的DEFAULT 值而不是NULL - 如果NULL 作为param_2 值提供。
类似这样的:
INSERT INTO my_table(val_1, val_2) VALUES (param_1, COALESCE(param_2, DEFAULT));
显然是错误的,因为INSERT 语句规范明确声明了一个表达式OR DEFAULT 可以使用,DEFAULT 本身在表达式中不可用。
我自己找到了两个解决方案,但我对它们并不满意。
- 从信息架构中选择
DEFAULT值并将其用于COALESCE表达式。
我不是专家,但似乎应该有一种更简单、更优雅的方法。
- 使用
INSERT,然后使用UPDATE
像这样:
-- ...
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;
-- ...
然而,这个解决方案有一个问题。生产系统的实际表有一些复杂的触发器,这些触发器在此表上的 UPDATE 语句上运行,因此我通常希望尽可能避免使用更新。
一般来说,我可能会坚持第二种解决方案,但这可能需要在上述触发器中添加一些技巧。但如果有办法避免这种情况 - 我将非常感谢您指出这一点。
【问题讨论】:
-
DEFAULT不能在表达式中使用,所以它不起作用。 -
这样你就可以构建动态 SQL 解决方案了。
-
由于
DEFAULT的工作方式,我认为您需要针对每种情况使用不同的INSERT语句。因此,要么使用IF param_2 IS NULL THEN ...在两个变体之间进行选择,要么构建一个动态语句并通过EXECUTE运行它 -
使用触发器附加/代替默认值。
标签: postgresql stored-procedures plpgsql postgresql-9.4