miércoles, 22 de febrero de 2012

SQL Serve - Utilizar Sentencia CASE

Para este ejemplo usaremos las Bases de Datos de ejemplo de sql server 2000, si lo prefieren pueden usar las de 2005 o 2008. Yo tengo SQL 2008 y tenía por ahí las Bases de datos de SQL 2000 Nortwind y Pubs, por eso usaré estas, en especifico Pubs, Tabla Authors para hacer los ejemplos.
Si no las tienen, las pueden descargar éstas desde las referencias.

Referencias:
URL MSDN CASE
http://msdn.microsoft.com/de-de/library/ms181765.aspx

Descargar Bases de Datos de Ejemplo SQL 2000
http://www.microsoft.com/download/en/details.aspx?id=23654

Como Instalar
Bases de Datos de Ejemplo SQL 2000
http://msdn.microsoft.com/es-es/library/ms227484%28v=vs.90%29.aspx


Tema.

Hoy voy a hablar sobre Transac SQL, específicamente sobre la sentencia CASE, lo primero que deben saber es que la sentencia case se utiliza en los bloques SELECT y WHERE.

En el bloque SELECT, generalmente se utiliza para dar formato, igual que el comando COALESCE, pero creo que tambien se pueden hacer otraz opciones la que la combierten en una sentencia más potente. Desde mi humilde perspectiva.

Anteriormente cuando queríamos discriminar que queríamos desplegar, generalmente construímos una sentencia dinámica en una variable y, mediante el comando exec la ejecutabamos.

Bloque SELECT

La sentencia CASE puede ser usada en el bloque Select, tal como se muestra a continuación

select
case when ltrim(rtrim(au_lname)) = 'White' then
UPPER(au_fname + ' ' + au_lname)
else
au_fname + ' ' + au_lname
end as [Nombre]
from
authors


O tambien podría ser usada de la siguiente forma

select
case when au_lname is not null and
au_fname is not null then
UPPER(au_fname + ' ' + au_lname)
else
case when au_lname is not null and
au_fname is null then
UPPER(au_lname)
else
case when au_lname is null and
au_fname is not null then
UPPER(au_fname)
else
''
end
end
end as [Nombre]
from
authors

Como ven esta sentencia se comporta como un bloque if, pero que puesde ser usada denstro de la consulta escrita en Transac SQL

Bloque WHERE

Bueno normalmente cuando escribíamos un SP, siempre cuando nos venían variables que se podían utilizar como filtro muchos de nosotos escribíamos una sentencia dinámica. Tal como se muestra a continuación, sino muy parecida.

declare @sql as nvarchar(2000)
declare @zip as char(5)
declare @state as char(2)

set @zip = null
set @state = null

set @sql = 'select * from authors'
if @zip is not null
begin
set @sql = @sql + ' where zip =' + @zip
end

if @zip is not null and @state is not null
begin
set @sql = @sql + ' and [state] =' + @state
end
else if @zip is null and @state is not null
begin
set @sql = @sql + ' where [state] =' + @state
end

exec (@sql)

Este funcionaba bien, cuando la sentencia retornaba pocos registros, cuando al Procedimiento Almacenado se le pasaban pocos parámetros y cuando ésta tenía un cuerpo pequeño, pero cuando esta hera muy grande y retornaba una gran cantidad de información, la cosa cambiaba. Claro que cambiaba, ya que el compilador de SQL tenía que hacer tres análisis (léxico, sintáctico y semántico) y despues ejecutaba la consulta.

Ahora y desde hace mucho tiempo podemos mejorar nuestras consultas evitando el análisis del compilador
(léxico, sintáctico y semántico) y mejorando en un tiempo considerable una consulta tal como se muestra a continuación:

declare @zip as char(5)
declare @state as char(2)
declare @name as varchar(20)

set @zip = null
set @state = null
set @name = null

select

*
from
authors
where
case when @zip is not null then
case when [zip] = @zip then 1 end
else 1 end = 1
and
case when @state is not null then
case when [state] = @state then 1 end
else 1 end = 1
and
case when @name is not null then
case when au_lname like '%' + @state + '%' or
au_fname like '%' + @state + '%' then 1 end
else 1 end = 1

Esto es un ejemplo muy básico de las posibles cosas que podrían hacer en SQL con case, espero que con esto puedan mejorar sus tiempos de respuesta en las sentencias SQL.

Salu2 y para cualquier duda aqui estamos.






No hay comentarios: