Saltar al contenido

OraclePL/SQL string problema de comparación

Te traemos el resultado a este rompecabezas, o por lo menos eso pensamos. Si sigues con alguna inquietud puedes escribirlo en el apartado de comentarios, para nosotros será un placer ayudarte

Solución:

Como señaló Phil, el vacío string se trata como NULL, y NULL no es igual o desigual a nada. Si espera cadenas vacías o NULL, deberá manejar aquellas con NVL():

 DECLARE
 str1  varchar2(4000);
 str2  varchar2(4000);
 BEGIN
   str1:='';
   str2:='sdd';
-- Provide an alternate null value that does not exist in your data:
   IF(NVL(str1,'X') != NVL(str2,'Y')) THEN
    dbms_output.put_line('The two strings are not equal');
   END IF;
 END;
 /

Sobre null comparaciones:

De acuerdo con la documentación de Oracle 12c sobre NULLS, null comparaciones usando IS NULL o IS NOT NULL evaluar a TRUE o FALSE. Sin embargo, todas las demás comparaciones se evalúan como UNKNOWN, noFALSE. La documentación establece además:

Una condición que se evalúa como DESCONOCIDA actúa casi como FALSA. Por ejemplo, una declaración SELECT con una condición en la cláusula WHERE que se evalúa como DESCONOCIDA no devuelve filas. Sin embargo, una condición que se evalúe como DESCONOCIDA difiere de FALSO en que las operaciones posteriores en una evaluación de condición DESCONOCIDA se evaluarán como DESCONOCIDA. Por lo tanto, NO FALSO se evalúa como VERDADERO, pero NO DESCONOCIDO se evalúa como DESCONOCIDO.

Oracle proporciona una tabla de referencia:

Condition       Value of A    Evaluation
----------------------------------------
a IS NULL       10            FALSE
a IS NOT NULL   10            TRUE        
a IS NULL       NULL          TRUE
a IS NOT NULL   NULL          FALSE
a = NULL        10            UNKNOWN
a != NULL       10            UNKNOWN
a = NULL        NULL          UNKNOWN
a != NULL       NULL          UNKNOWN
a = 10          NULL          UNKNOWN
a != 10         NULL          UNKNOWN

También aprendí que no debemos escribir PL/SQL asumiendo que las cadenas vacías siempre se evaluarán como NULL:

Oracle Database actualmente trata un valor de carácter con una longitud de cero como null. Sin embargo, esto no puede seguir siendo true en futuras versiones, y Oracle recomienda que no trate las cadenas vacías como si fueran nulos.

Completemos los espacios en su código, agregando las otras ramas en la lógica, y veamos qué sucede:

SQL> DECLARE
  2   str1  varchar2(4000);
  3   str2  varchar2(4000);
  4  BEGIN
  5     str1:='';
  6     str2:='sdd';
  7     IF(str1<>str2) THEN
  8      dbms_output.put_line('The two strings is not equal');
  9     ELSIF (str1=str2) THEN
 10      dbms_output.put_line('The two strings are the same');
 11     ELSE
 12      dbms_output.put_line('Who knows?');
 13     END IF;
 14   END;
 15  /
Who knows?

PL/SQL procedure successfully completed.

SQL>

Entonces, ¿las dos cadenas no son iguales ni no son iguales? ¿Eh?

Todo se reduce a esto. Oracle trata un vacío string como NULL. Si intentamos comparar un NULL y otro string el resultado no es VERDADERO ni FALSO, es NULO. Este sigue siendo el caso incluso si el otro string es también un NULL.

comparo cadenas usando = y no <>. He descubierto que en este contexto = parece funcionar de manera más razonable que <>. He especificado que dos cadenas vacías (o NULL) son iguales. La implementación real devuelve PL/SQL booleano, pero aquí lo cambié a pls_integer (0 es false y 1 es true) para poder demostrar fácilmente la función.

create or replace function is_equal(a in varchar2, b in varchar2)
return pls_integer as
begin
  if a is null and b is null then
    return 1;
  end if;

  if a = b then
    return 1;
  end if;

  return 0;
end;
/
show errors

begin
  /* Prints 0 */
  dbms_output.put_line(is_equal('AAA', 'BBB'));
  dbms_output.put_line(is_equal('AAA', null));
  dbms_output.put_line(is_equal(null, 'BBB'));
  dbms_output.put_line(is_equal('AAA', ''));
  dbms_output.put_line(is_equal('', 'BBB'));

  /* Prints 1 */
  dbms_output.put_line(is_equal(null, null));
  dbms_output.put_line(is_equal(null, ''));
  dbms_output.put_line(is_equal('', ''));
  dbms_output.put_line(is_equal('AAA', 'AAA'));
end;
/

Si haces scroll puedes encontrar los informes de otros desarrolladores, tú además tienes el poder insertar el tuyo si te apetece.

¡Haz clic para puntuar esta entrada!
(Votos: 0 Promedio: 0)



Utiliza Nuestro Buscador

Deja una respuesta

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *