Fran Otero

Programación C#, ASP.NET,SqlServer, Mobile y electrónica.

¿Por qué cambiar IsNull por Coalesce?

IsNull es la función de Sql Server que la mayoría de los programadores que llevan unos años escribiendo consultas utilizan. Su función es devolver un valor por defecto si el primer argumento pasado es nulo.

Por ejemplo, supongamos que tenemos la siguiente tabla:

declare @Clientes as table (Id int, Nombre varchar(100));

 Y queremos actualizar un campo determinado, por ejemplo el Id=2, para que el nombre coincida con un parámetro que nos pasarán desde programa. Entonces la consulta a ejecutar sería tan sencilla como esta:

update @Clientes set Nombre = @NuevoNombre where Id=2;

Ahora  queremos mejorar nuestra consulta, de forma que si el parámetro @NuevoNombre es nulo la fila no se actualice y mantenga su valor. Entonces podríamos substituir la segunda línea por cualquiera de estas dos opciones:

        a) set Nombre=IsNull(@NuevoNombre,Nombre);

        b) set Nombre=Coalesce(@NuevoNombre,Nombre) 

 Siempre que el parámetro esté correctamente definido ambas consultas se comportarán igual. El problema viene cuando el parámetro (por ejemplo por utilizar inferencia en el sistema de origen) viene con una definición distinta. Imaginemos por ejemplo que definimos así el parámetro y ejecutamos la consulta:

declare @NuevoNombre as varchar(2)= null;

En el update con calesce el resultado es el esperado, mientras que en el caso de IsNull, la tabla se actualizará incorrectamente. Esto es debido a que realmente IsNull no devuelve el segundo parámetro, sino el resultado de convertir el valor del segundo parámetro al tipo del primero, lo cual consituye una diferencia fundamental.

A continuación listamos el código completo para copiar y pegar y demostrar el funcionamiento. Basta con descomentar alternativamente uno u otro UPDATE para comparar los resultados.

declare @Clientes as table ( Id int, Nombre varchar(100));
insert into @Clientes values
    (1,'Francisco Otero'),
    (
2,'Otro fulano');

declare @NuevoNombre as varchar(2)=null;
--update @Clientes
--set Nombre= @NuevoNombre
--where Id=2

--update @Clientes
--set Nombre=Coalesce(@NuevoNombre,Nombre)
--where Id=1

select * from @Clientes;
Posted: 9/9/2010 21:00 por Fran Otero Otero | con 7 comment(s)
Archivado en:
Comparte este post:

Comentarios

Isidro ha opinado:

Muy util gracias.

# September 10, 2010 5:13 AM

Juan Irigoyen ha opinado:

Interesante, aunque en el ejemplo que propones no seria más adecuado escribir algo como 'WHERE @NuevoNombre IS NOT NULL'. Un saludo.

# September 10, 2010 9:40 AM

Javier López González ha opinado:

Personalmente nunca he usado el IsNull mas que en SELECT, cuando se que una columna puede tener nulos, y por el motivo que sea quiero un valor por defecto (cadena vacía para concatenaciones por ejemplo).

Para controlar que no se meten nulos creo que lo mejor es una restricción que indique que la columna no admite nulos, si no en todas las partes donde toques esa columna tendrás que hacer lo necesario para que no se metan nulos, y si se te olvida en un sitio, te quedas con un modelo de datos que no cumple lo que tu crees que cumple.

Un saludo

# September 10, 2010 10:00 AM

Pedro ha opinado:

Gran Post - seguro que a muchos nos será de gran utilidad algún dia ... buscando el expediente X.

Pero personalemente creo que la solucion no es cambiar la funcion isNull por Coalesce - sino cambiar la longitud de la variable. Son funciones diferentes y tienen uso diferente (aunque en el caso concreto de Coalesce con un solo parametro actue igual que isNull).

Saludos,

Pedro

# September 10, 2010 11:12 AM

Fran Otero Otero ha opinado:

Tenéis razón, no es el ejemplo más ilustrativo, pero quería demostrar el efecto.

Estoy de acuerdo que lo normal es utilizarlo en selects: el efecto será el mismo. Por ejemplo si tratamos de hacer un "select isnull(nombre,'Usuario Anónimo') from algo", la cadena "Usuario Anónimo" se recortará a la longitud del campo nombre. Con coallesce eso no nos pasaría.

Gracias a todos por los comentarios.

# September 10, 2010 7:10 PM

Quique Martínez ha opinado:

Buen ejemplo, ahora solo acordarme en la próxima consulta..

thanks!

# September 13, 2010 5:35 PM

hpuma ha opinado:

bueno esta  de mucha  ayuda tu ejemplo pero dime  como es el codigo en  lenguaje java; por que  io  estoy   hibernate ps haber si lo cambias: de  ambos  restriction.isNull  y  restriction.isNotNull........

gracias.

saludos!!!!!!!!

# November 18, 2010 6:21 PM