Estou tentando ter uma NVL
função no postgres.
create or replace function nvl (anyelement, anyelement)
returns anyelement language sql as $$
select coalesce(cast( $1 as decimal), cast( $2 as decimal))
$$;
no entanto, isso falha em mim para os seguintes exemplos:
testdb=> select nvl(1,2);
ERROR: return type mismatch in function declared to return integer
DETAIL: Actual return type is numeric.
CONTEXT: SQL function "nvl" during inlining
testdb=> SELECT nvl( sum(balance), 0 ) as b FROM db.bank WHERE user = 123;
ERROR: function nvl(numeric, integer) does not exist
LINE 1: SELECT nvl( sum(balance), 0 ) as b FROM db.bank...
^
HINT: No function matches the given name and argument types. You might need to add explicit type casts.
Quando eu altero para:
create or replace function nvl (anyelement, anyelement)
returns anyelement language sql as $$
select case when $1 is null then $2 else $1 END
$$;
O primeiro exemplo funciona. Mas ainda tenho falhas com:
testdb=> SELECT nvl( sum(balance), 0 ) as b FROM db.bank WHERE user = 123;
ERROR: function nvl(numeric, integer) does not exist
LINE 1: SELECT nvl( sum(balance), 0 ) as b FROM db.bank...
Gostaria de uma ajuda para consertar isso.
Os erros resultam de um mal-entendido sobre o uso do
anyelement
tipo. Leia na documentação :Então, você deve usar a função na forma que foi proposta :
e certifique-se de que o tipo real de argumentos corresponda exatamente. Se a coluna
balance
for numérica, o segundo argumento também deve sernumeric
:Atualizar. O OP diz:
Neste caso, você não pode usar
anyelement
argumentos. Você precisa criar uma função com argumentos numéricos:A desvantagem é que a função funcionará apenas para argumentos numéricos e/ou inteiros. Postgres permite sobrecarregar funções, então você pode criar funções adicionais para outros tipos, por exemplo: