Olá! Hoje vamos explorar duas funções muito úteis no Oracle PL/SQL: NULLIF e COALESCE. Essas funções são como atalhos para expressões CASE, tornando nosso código mais limpo e eficiente. Vamos mergulhar nesse assunto?
Introdução
Antes de começarmos, é importante saber que tanto NULLIF quanto COALESCE são definidas pelo padrão ANSI 1999 como “abreviações de CASE”. Isso significa que elas podem ser usadas como variações da expressão CASE, mas de uma forma mais concisa e fácil de ler.
A função NULLIF
1 |
NULLIF(EXPRESSAO1, EXPRESSAO2) |
- Se EXPRESSAO1 for igual a EXPRESSAO2, a função retorna NULL.
- Se forem diferentes, ela retorna o valor de EXPRESSAO1.
É quase como o oposto da função NVL, que você já deve conhecer. A função NVL é usada para substituir um valor NULL por um valor padrão. Relembrando a sintaxe da NVL:
1 |
NVL(expressao1, expressao2) |
- Se expressao1 for NULL, retorna expressao2
- Se expressao1 não for NULL, retorna expressao1
Exemplo de NVL:
1 2 3 4 5 6 7 |
DECLARE v_valor1 NUMBER := NULL; v_valor2 NUMBER := 10; BEGIN DBMS_OUTPUT.PUT_LINE('NVL(v_valor1, 0): ' || NVL(v_valor1, 0)); DBMS_OUTPUT.PUT_LINE('NVL(v_valor2, 0): ' || NVL(v_valor2, 0)); END; |
A função NULLIF, por outro lado, compara duas expressões e retorna NULL se forem iguais.
Veja um exemplo prático:
1 2 3 4 5 6 7 |
DECLARE v_num NUMBER := &sv_user_num; v_remainder NUMBER; BEGIN v_remainder := NULLIF(MOD(v_num, 2), 0); DBMS_OUTPUT.PUT_LINE('v_remainder: ' || v_remainder); END; |
Neste exemplo, estamos verificando se um número é par ou ímpar. Se for par (resto 0), o NULLIF retorna NULL. Se for ímpar, retorna o resto.
Se você rodar isso com o número 5, verá:
1 2 |
v_remainder: 1 |
Mas se rodar com 4:
1 2 |
v_remainder: |
Interessante, não é? Com o 4, o resto é 0, então o NULLIF retorna NULL, que aparece como um espaço em branco.
Comparação
Agora, vamos ver um exemplo que mostra como elas podem ser vistas como complementares:
1 2 3 4 5 6 7 8 9 |
DECLARE v_valor NUMBER := 0; BEGIN -- Usando NVL para substituir 0 por NULL DBMS_OUTPUT.PUT_LINE('NVL: ' || NVL(v_valor, NULL)); -- Usando NULLIF para transformar 0 em NULL DBMS_OUTPUT.PUT_LINE('NULLIF: ' || NULLIF(v_valor, 0)); END; |
Resultado:
1 2 3 |
NVL: 0 NULLIF: |
Neste exemplo:
- NVL mantém o valor 0 porque ele não é NULL
- NULLIF transforma o valor 0 em NULL porque ele é igual ao segundo argumento
Veja como elas agem de forma oposta neste cenário específico:
- NVL tenta evitar NULL, substituindo-o por um valor padrão
- NULLIF pode criar um NULL quando encontra um valor específico
Ah, e tem um detalhe importante: você não pode usar NULL diretamente como primeiro argumento do NULLIF. Por exemplo, isso dará erro:
1 2 3 4 5 6 |
DECLARE v_remainder NUMBER; BEGIN v_remainder := NULLIF(NULL, 0); DBMS_OUTPUT.PUT_LINE('v_remainder: ' || v_remainder); END; |
Isso resultará em um erro de sintaxe. O Oracle não permite que você use um literal NULL como primeiro operando da expressão NULLIF.
Embora NULLIF e NVL não sejam exatamente opostos em todos os casos, eles podem ter efeitos opostos em certas situações:
- NVL transforma NULL em um valor não-nulo
- NULLIF pode transformar um valor não-nulo em NULL
A chave para entender a diferença está nos seus propósitos:
- Use NVL quando quiser um valor padrão no lugar de NULL
- Use NULLIF quando quiser transformar um valor específico em NULL
A função COALESCE
Agora, vamos falar da COALESCE. Essa função é como uma detetive em busca do primeiro valor não-nulo em uma lista de expressões. Ela funciona assim:
1 |
COALESCE(EXPRESSAO1, EXPRESSAO2, ..., EXPRESSAON) |
A COALESCE avalia cada expressão da esquerda para a direita e retorna o valor da primeira expressão que não seja NULL. Se todas forem NULL, ela retorna NULL.
É como se fosse uma série de funções NVL aninhadas:
1 |
NVL(EXPRESSAO1, NVL(EXPRESSAO2, NVL(EXPRESSAO3, ...))) |
Antes de aplicarmos um exemplo prático, vamos criar uma tabela para aplicar o conceito
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 |
-- Criação da tabela ENROLLMENT CREATE TABLE enrollment ( student_id NUMBER, section_id NUMBER, final_grade NUMBER ); -- Criação da tabela GRADE CREATE TABLE grade ( student_id NUMBER, section_id NUMBER, grade_type_code VARCHAR2(2), numeric_grade NUMBER ); -- Inserção de dados na tabela ENROLLMENT INSERT INTO enrollment (student_id, section_id, final_grade) VALUES (102, 86, NULL); INSERT INTO enrollment (student_id, section_id, final_grade) VALUES (102, 89, 92); -- Inserção de dados na tabela GRADE INSERT INTO grade (student_id, section_id, grade_type_code, numeric_grade) VALUES (102, 86, 'FI', 85); INSERT INTO grade (student_id, section_id, grade_type_code, numeric_grade) VALUES (102, 89, 'FI', 92); -- Commit para salvar as alterações COMMIT; |
Agora que temos nossas tabelas criadas e populadas, vamos ver como a função COALESCE funciona na prática. Aqui está nossa consulta:
1 2 3 4 5 6 7 8 9 10 11 |
SELECT e.student_id, e.section_id, e.final_grade, g.numeric_grade, COALESCE(e.final_grade, g.numeric_grade, 0) AS grade FROM enrollment e, grade g WHERE e.student_id = g.student_id AND e.section_id = g.section_id AND e.student_id = 102 AND g.grade_type_code = 'FI'; |
Quando executamos esta consulta, obtemos o seguinte resultado:
1 2 3 |
STUDENT_ID SECTION_ID FINAL_GRADE NUMERIC_GRADE GRADE 102 86 (null) 85 85 102 89 92 92 92 |
Vamos analisar o que está acontecendo aqui:
- Na primeira linha do resultado:
final_grade
é NULL- COALESCE passa para a próxima expressão,
numeric_grade
, que é 85 - Portanto, COALESCE retorna 85
- Na segunda linha do resultado:
final_grade
não é NULL (é 92)- COALESCE retorna imediatamente este valor, sem precisar olhar para
numeric_grade
Observe como a COALESCE nos ajuda a lidar elegantemente com o valor NULL na primeira linha, fornecendo um valor alternativo da tabela grade
. Isso é particularmente útil quando temos várias fontes possíveis para um valor e queremos usar a primeira que não seja NULL.
Este exemplo demonstra a flexibilidade da função COALESCE em situações reais de banco de dados, onde podemos ter valores ausentes ou incompletos em algumas tabelas e precisamos de uma maneira consistente de lidar com esses casos.
Lembre-se de que você pode adaptar este exemplo para suas próprias necessidades, alterando as condições do WHERE ou adicionando mais expressões à função COALESCE conforme necessário.
COALESCE e CASE
É interessante notar que a COALESCE pode ser reescrita como uma expressão CASE. Por exemplo:
1 |
COALESCE(EXPRESSAO1, EXPRESSAO2) |
é equivalente a:
1 2 3 4 |
CASE WHEN EXPRESSAO1 IS NOT NULL THEN EXPRESSAO1 ELSE EXPRESSAO2 END |
E para múltiplas expressões:
1 |
COALESCE(EXPRESSAO1, EXPRESSAO2, ..., EXPRESSAON) |
é equivalente a:
1 2 3 4 5 6 |
CASE WHEN EXPRESSAO1 IS NOT NULL THEN EXPRESSAO1 WHEN EXPRESSAO2 IS NOT NULL THEN EXPRESSAO2 ... ELSE EXPRESSAON END |
Conclusão
NULLIF e COALESCE são ferramentas poderosas para lidar com valores nulos de forma elegante e eficiente. A NULLIF nos ajuda a transformar igualdades em NULL, enquanto a COALESCE nos permite encontrar o primeiro valor não-nulo em uma lista de expressões.
Lembre-se:
- Use NULLIF quando quiser comparar duas expressões e retornar NULL se forem iguais.
- Use COALESCE quando quiser encontrar o primeiro valor não-nulo em uma série de expressões.
Pratique com essas funções e você verá como elas podem tornar seu código PL/SQL mais limpo e eficiente. Na próxima vez que você se deparar com valores nulos, terá duas novas armas no seu arsenal!