de Martin LE TARNEC.

Cadenas numéricas


Las cadenas numéricas son números que se almacenan en columnas de texto. Aunque es una muy mala práctica, no deja automáticamente un índice inútil si se trata como una cadena de caracteres:

SELECT ...
  FROM ...
 WHERE numeric_string = '42'

Por supuesto, esta sentencia puede utilizar un índice sobre NUMERIC_STRING. Si se compara a un número, sin embargo, la base de datos puede no usar esa condición como un predicado de acceso.

SELECT ...
  FROM ...
 WHERE numeric_string = 42

Cuidado con potenciales acciones invisibles al usuario. Aunque algunas bases de datos producen un error (p.ej. PostgreSQL), muchas bases de datos agregan solamente una conversión implícita.

SELECT ...
  FROM ...
 WHERE TO_NUMBER(numeric_string) = 42

Es el mismo problema que antes. Un índice sobre NUMERIC_STRING no puede utilizarse debido a la función llamada. La solución es la misma que antes: no convertir la columna de la tabla; en su lugar, convertir el criterio de la búsqueda.

SELECT ...
  FROM ...
 WHERE numeric_string = TO_CHAR(42)

Se podría preguntar porqué la base de datos no lo hace así de forma automática. Es porque convertir una cadena de caracteres hacia un número da siempre resultados correctos. Eso no se aplica a la inversa. Un número, formateado en texto, puede contener espacios, puntuaciones, y tener ceros como primer carácter. Un solo valor puede escribirse de varias maneras:

42
042
0042
00042
...

La base de datos no puede saber el formato del número usado dentro de la columna NUMERIC_STRING pero sí aplica a la inversa: la base de datos convierte el número en cadena de caracteres sin problema; es una transformación sin equivocación posible.

La función TO_CHAR devuelve solamente una representación de cadenas para los números. Coincide solamente el primero de los caracteres de las cadenas listadas. Si se usa TO_NUMBER, coinciden todos ellos. Eso significa que existe no solamente una diferencia de rendimiento entre las dos variantes ¡sino también una diferencia semántica!

Usar cadenas numéricas es generalmente problemático: la mayor parte de ellas causan problemas de rendimiento debido a la conversión implícita y también introducen un riesgo de ejecución con los errores de conversiones debido a números inválidos. Aunque la sentencia sea la más trivial y no use funciones dentro del filtro where, puede causar una interrupción debido a un error de conversión solamente con que exista un número inválido almacenado en la tabla.

Sugerencia

Usa tipos numéricos para almacenar números.

Observa que el problema no existe a la inversa:

SELECT ...
  FROM ...
 WHERE numeric_number = '42'

La base de datos transformará consistentemente cadenas de caracteres hacia un número. No aplica una función sobre la columna potencialmente indexada: funcionará un índice estándar. Aun así, es posible hacer una conversión manual incorrecta:

SELECT ...
  FROM ...
 WHERE TO_CHAR(numeric_number) = '42'

Si te gusta mi manera de explicar, te encantará mi libro.

Acerca del autor

Foto de Markus Winand

Markus Winand enseña eficientemente SQL, en casa y online. Minimiza el tiempo de desarrollo utilizando moderno SQL y optimiza el tiempo de ejecución con indexación inteligente. Para ello también ha publicado el libro SQL Performance Explained.

“Use The Index, Luke” de Markus Winand se halla bajo licencia Creative Commons Attribution-Noncommercial-No Derivative Works 3.0 Unported License.
Aspectos legales | Contacto | SIN GARANTÍA | Marcas | Privacy | CC-BY-NC-ND 3.0 licencia