Aprenda PL/SQL

Este caso é no mí­nimo curioso! É bem comum usarmos “IN” quando queremos que o banco considere várias opções para um determinado campo. Neste exemplo, vamos demonstrar que o ORACLE concatena espaços em branco em comparações com IN. Vamos aos exemplos:

Sabemos que o otimizador substitui todas opções do IN pra vários “OR” no SQL. No exemplo abaixo, vamos deixar o primeiro “SP” com um espaço em branco na direita! Não deveria retornar nenhuma linha:

SQL> SELECT 'SQL IN contatena espaços em branco!' CAMPO
2 FROM DUAL
3 WHERE 'SP ' IN ( 'SP', 'RJ' )
4 /

CAMPO
-----------------------------------
SQL IN contatena espaços em branco!

SQL>

Agora, o mesmo teste com o TAB:
SQL> SELECT 'SQL IN contatena TAB!' CAMPO
2 FROM DUAL
3 WHERE 'SP ' IN ( 'SP', 'RJ' )
4 /

CAMPO
---------------------
SQL IN contatena TAB!

SQL>

Agora, tentamos o mesmo com espaço em branco na esquerda:
SQL> SELECT 'SQL IN não concatena espaços na esquerda!' CAMPO
2 FROM DUAL
3 WHERE ' SP' IN ( 'SP', 'RJ' )
4 /

no rows selected

SQL>

Agora, dentro de um bloco PL/SQL
SQL> DECLARE
2 VTEMP VARCHAR2(100);
3 BEGIN
4 SELECT 'SQL IN contatena espaços em branco!' CAMPO
5 INTO VTEMP
6 FROM DUAL
7 WHERE 'SP ' IN ( 'SP', 'RJ' );
8
9 DBMS_OUTPUT.PUT_LINE('Concatenou');
10
11 EXCEPTION WHEN NO_DATA_FOUND THEN
12 DBMS_OUTPUT.PUT_LINE('Nao concatenou');
13 END;
14 /
Concatenou

PL/SQL procedure successfully completed.

SQL>

Interessante: Usando variável, ele não faz isso!
SQL> DECLARE
2 VTEMP VARCHAR2(100);
3 VALOR VARCHAR2(10) :='SP ';
4 BEGIN
5 SELECT 'SQL IN contatena espaços em branco!' CAMPO
6 INTO VTEMP
7 FROM DUAL
8 WHERE valor IN ( 'SP', 'RJ' );
9
10 DBMS_OUTPUT.PUT_LINE('Concatenou');
11
12 EXCEPTION WHEN NO_DATA_FOUND THEN
13 DBMS_OUTPUT.PUT_LINE('Nao concatenou');
14 END;
15 /
Nao concatenou

PL/SQL procedure successfully completed.

SQL>

CONCLUSÃO
Mais uma prova que usar BINDS é sempre uma boa. “Montar” comandos SQL dinamicamente pode acarretar essa concatenação acima.

EXPLICAÇÃO PARA O CASO

Após uma pesquisa na internet sobre o assunto, verificamos um texto de Chip Dawes que diz o seguinte:

Blank-Padded and Nonpadded Comparison Semantics

With blank-padded semantics, if the two values have different lengths, then Oracle first adds blanks to the end of the shorter one so their lengths are equal. Oracle then compares the values character by character up to the first character that differs. The value with the greater character in the first differing position is considered greater. If two values have no differing characters, then they are considered equal. This rule means that two values are equal if they differ only in the number of trailing blanks. Oracle uses blank-padded comparison semantics only when both values in the comparison are either expressions of datatype CHAR, NCHAR, text literals, or values returned by the USER function.

OU seja, o Oracle concatena espaços em branco na string menor para que tenham o mesmo tamanho. Após isso, ele faz a comparação das strings. Se nenhuma letra é diferente, então são iguais.

Caso encerrado!

Comments are closed.