当参数为NULL时,将DEFAULT值插入列中
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了当参数为NULL时,将DEFAULT值插入列中相关的知识,希望对你有一定的参考价值。
我想写一个这样的存储过程:
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
语句上运行,因此我通常希望尽可能避免使用更新。
一般来说,我可能会坚持使用第二种解决方案,但可能需要在上述触发器中添加一些黑客。但如果有办法避免这种情况 - 我将非常感激地指出它。
由于param_2
只能是null
或not null
中的一个,因此只有一个选择将返回要插入的行:
with i as (
insert into my_table (val_1)
select param_1
where param_2 is null
)
insert into my_table (val_1, val_2)
select param_1, param_2
where param_2 is not null
如果有必要返回插入的值:
with i_null as (
insert into my_table (val_1)
select param_1
where param_2 is null
returning *
), i_notnull as (
insert into my_table (val_1, val_2)
select param_1, param_2
where param_2 is not null
returning *
)
select * from i_null
union all
select * from i_notnull
评论有点长。
一种方法是声明列NOT NULL
。插入NULL
值会产生约束违规,您可以使用insert
在on constraint
中捕获。
这似乎是一种正确的方法。如果列具有默认值,那么您可能不希望它是NULL
。
使用dynamic-SQL:
CREATE OR REPLACE FUNCTION my_function(param_1 text, param_2 text DEFAULT NULL::text)
RETURNS bigint AS
$$
DECLARE ret bigint;
BEGIN
EXECUTE 'INSERT INTO my_table(val_1, val_2) VALUES (' ||
quote_literal(param_1) || ',' ||
CASE WHEN param_2 IS NULL THEN 'DEFAULT' ELSE quote_literal(param_2) END ||
')';
RETURN ret;
END;
$$
LANGUAGE plpgsql;
如果insert和问题一样简单,我会使用两个不同的INSERT
语句,因为生成的代码很小且可读且快速:
IF param_2 IS NULL THEN
INSERT INTO my_table(val_1) VALUES (param_1);
ELSE
INSERT INTO my_table(val_1, val_2) VALUES (param_1, param_2);
END IF;
对于具有更高复杂度的插入,例如使用多个可选参数,我可以选择上面的@ lad2025的动态SQL解决方案。
以上是关于当参数为NULL时,将DEFAULT值插入列中的主要内容,如果未能解决你的问题,请参考以下文章
使用默认 FIREBIRD 将 null 插入非 null 列