¿Usar CONCAT o CONCAT_WS en MySQL?

publicado por: Anonymous

Como ya sabemos, MySQL cuenta con dos funciones para concatenar cadenas: CONCAT y CONCAT_WS.

Respondiendo a una pregunta, vi que CONCAT no arroja los resultados esperados cuando al menos uno de los valores es igual a NULL.

¿Cuándo se recomienda entonces usar CONCAT y cuándo usar CONCAT_WS?

solución

I. Lo que dice la documentación

Veamos primero lo que explica la documentación sobre ambas funciones:

CONCAT()

CONCAT() devuelve NULL si cualquiera de sus argumentos es NULL.

Dicho de otro modo, cualquier valor NULL que entre en un CONCAT anula a los demás valores.

CONCAT_WS()

CONCAT_WS() no omite cadenas vacías. Sin embargo, omite cualquier
valor NULL después del argumento del separador.


II. Determinando cuál usar en un escenario real

Supongamos un diseño de tabla como este:

CREATE TABLE  IF NOT EXISTS persona 
    (
      persona_id          INT NOT NULL PRIMARY KEY AUTO_INCREMENT,
      nombre              VARCHAR(50) NOT NULL,
      apellido_paterno    VARCHAR(50),
      apellido_materno    VARCHAR(50) NOT NULL
    );

(a) El problema de CONCAT con los valores NULL

El diseño de tabla mostrado más arriba es un diseño común, de hecho, cualquier tabla podría tener columnas como apellido_paterno, es decir, columnas que admitan valores NULL. Y no solo eso, en cualquier inserción que no asigne valores a esas columnas, su valor por defecto será NULL.

Eso significa que, si hacemos una inserción parecida a esta:

INSERT INTO persona (nombre, apellido_materno) 
            VALUES  ('Pedro','Pérez');

la columna apellido_paterno recibirá por defecto el valor NULL.

Si nosotros usamos CONCAT en nuestra tabla persona:

-- Tratamiento de NULL con CONCAT ... ¡terrible!

SELECT CONCAT(
              apellido_paterno, ' ', apellido_materno, ', ', nombre
             ) datos FROM persona;

El resultado, en el caso de Pedro Pérez será:

    datos
1   NULL

O sea, ni Pedro, ni Pérez, ni nada… solamente NULL. Verdaderamente terrible ¿no?

Nótese que NULL y una cadena vacía no son lo mismo. Probemos otro INSERT:

INSERT INTO persona (nombre, apellido_paterno, apellido_materno) 
            VALUES  ('Juan', '', 'Arias');

Como eres observador, has visto que la columna apellido_paterno está recibiendo una cadena vacía ''.

Y veremos que CONCAT() es amigo de las cadenas vacías… Es que CONCAT() tiene sus preferencias… no es justo, ¡no! 🙂

El resultado del SELECT anterior para Juan Arias será:

    datos
3    Arias, Juan

El problema es que cuando no se indica ningún valor explícitamente, la columna adquiere un valor NULL y eso es terrible si usamos CONCAT.


(b) El comportamiento de CONCAT_WS()

Veamos qué tal se comporta CONCAT_WS() con nuestro amigo Pedro Pérez:

-- Tratamiento de NULL con CONCAT_WS ... ¡genial +!

SELECT CONCAT_WS(
                  ' ', apellido_paterno, apellido_materno, nombre
                ) datos 
        FROM persona;

Daría como resultado:

    datos
1   Pérez Pedro

¿Y con Juan Arias?:

    datos
3    Arias Juan

¡Este CONCAT_WS entonces es casi una maravilla!

Según su sintaxis, hay que poner el separador al principio solamente, y luego la lista de columnas o valores que queremos concatenar. Si el separador es el mismo es maravilloso, pero ¿y si necesito diferentes separadores?.

¡Podemos hacerlo!, poniendo una cadena vacía como separador y concatenando las columnas y valores como hacemos con CONCAT(), o sea, handmade:

-- Tratamiento de NULL con CONCAT_WS y varios separadores ... ¡genial ++!

SELECT CONCAT_WS(
                  '', apellido_paterno, ' ', apellido_materno, ', ' ,nombre
                ) datos 
        FROM persona;

El resultado sería:

    datos
1    Pérez, Pedro
2   Ruiz García, Santiago
3    Arias, Juan

Bueno, pero… ¡hay un espacio en blanco cuando falta algún dato! Eso tiene solución, te toca a ti buscarla.


III. Conclusión

Visto que CONCAT():

  • No es amigo de los valores NULL
  • Nos obliga a repetir el separador aún en los casos en que el separador no cambia

Y visto que CONCAT_WS():

  • Es amigo de los valores NULL
  • Puede ser usado como si fuese CONCAT() en los casos en que el separador cambia

Podemos concluir que se puede usar CONCAT_WS() en todos los casos y si se quiere usar CONCAT() debemos estar totalmente seguros de que todos los valores que intervienen ninguno es NULL.


Una demo completa del código usado en la respuesta se puede encontrar aquí.

Respondido por: Anonymous

Leave a Reply

Your email address will not be published. Required fields are marked *