Existem diferenças não óbvias entre NVL e Coalesce no Oracle?
As diferenças óbvias são que a coalescência retornará o primeiro item não nulo em sua lista de parâmetros, enquanto nvl usa apenas dois parâmetros e retorna o primeiro se não for nulo; caso contrário, retorna o segundo.
Parece que o NVL pode ser apenas uma versão do 'Case Base' de coalescência.
Estou esquecendo de algo?
Respostas:
COALESCE
é uma função mais moderna que faz parte doANSI-92
padrão.NVL
éOracle
específico, foi introduzido em80
antes de haver padrões.No caso de dois valores, eles são sinônimos.
No entanto, eles são implementados de maneira diferente.
NVL
sempre avalia os dois argumentos, enquantoCOALESCE
geralmente interrompe a avaliação sempre que encontra a primeira nãoNULL
(existem algumas exceções, como sequênciaNEXTVAL
):Isso funciona por quase
0.5
segundos, uma vez que geraSYS_GUID()
, apesar de1
não ser umNULL
.Isso entende que
1
não é umNULL
e não avalia o segundo argumento.SYS_GUID
não são gerados e a consulta é instantânea.fonte
O NVL fará uma conversão implícita no tipo de dados do primeiro parâmetro, portanto, o seguinte não erro
O COALESCE espera tipos de dados consistentes.
lançará um 'erro de tipo de dados inconsistente'
fonte
NVL e COALESCE são usados para obter a mesma funcionalidade de fornecer um valor padrão, caso a coluna retorne um NULL.
As diferenças são:
Exemplos para o terceiro caso. Outros casos são simples.
select nvl('abc',10) from dual;
funcionaria como o NVL fará uma conversão implícita do numérico 10 em string.select coalesce('abc',10) from dual;
falhará com Erro - tipos de dados inconsistentes: CHAR esperado obteve NUMBERExemplo para caso de uso UNION
falha com
ORA-00932: inconsistent datatypes: expected CHAR got DATE
consegue.
Mais informações: http://www.plsqlinformation.com/2016/04/difference-between-nvl-and-coalesce-in-oracle.html
fonte
Também há diferença no manuseio do plano.
O Oracle pode formar um plano otimizado com concatenação de filtros de ramificação quando a pesquisa contém comparação de
nvl
resultado com uma coluna indexada.nvl:
coalescer:
Os créditos vão para http://www.xt-r.com/2012/03/nvl-coalesce-concatenation.html .
fonte
Outra prova de que coalescer () não interrompe a avaliação com o primeiro valor não nulo:
Execute isso e verifique
my_sequence.currval;
fonte
Na verdade, não posso concordar com cada afirmação.
"COALESCE espera que todos os argumentos sejam do mesmo tipo de dados."
Isso está errado, veja abaixo. Os argumentos podem ser tipos de dados diferentes, também documentados : Se todas as ocorrências de expr forem do tipo numérico ou qualquer tipo de dado não numérico que possa ser implicitamente convertido em um tipo de dado numérico, o Oracle Database determinará o argumento com a maior precedência numérica, implicitamente converte os argumentos restantes para esse tipo de dados e retorna esse tipo de dados. . Na verdade, isso contradiz a expressão comum "COALESCE para na primeira ocorrência de um valor não nulo"; caso contrário, o caso de teste n ° 4 não deve gerar um erro.
Também de acordo com o caso de teste n ° 5,
COALESCE
faz uma conversão implícita de argumentos.fonte
Embora este seja óbvio, e até mencionado de uma maneira apresentada por Tom, que fez essa pergunta. Mas vamos colocar de novo.
NVL pode ter apenas 2 argumentos. A coalescência pode ter mais de 2.
select nvl('','',1) from dual;
// Resultado::ORA-00909
número inválido de argumentosselect coalesce('','','1') from dual;
// Saída: retorna 1fonte
NVL: Substitua nulo por valor.
COALESCE: Retorne a primeira expressão não nula da lista de expressões.
Tabela: PRICE_LIST
Abaixo está o exemplo de
[1] Defina o preço de venda com a adição de 10% de lucro a todos os produtos.
[2] Se não houver preço de tabela de compra, o preço de venda é o preço mínimo. Para liquidação.
[3] Se também não houver preço mínimo, defina o preço de venda como preço padrão "50".
Explique com um exemplo prático da vida real.
Você pode ver que, com o NVL, podemos alcançar as regras [1], [2],
mas com o COALSECE, podemos alcançar as três regras.
fonte
NVL(Purchase_Price + (Purchase_Price * 0.10), nvl(Min_Price,50))
. Ou sobre:nvl(NVL(Purchase_Price + (Purchase_Price * 0.10), Min_Price) ,50)
:)