Diario de SQL Server

Crear una udl para comprobar una conexión

Escrito por qwalgrande 29-05-2010 en General. Comentarios (4)

En la resolución de problemas de conexión es frecuente la necesidad de verificar los parámetros de una cadena de conexión. Lo más fácil para ello es crear una udl, introducir los parámetros y hacer un test.

 

Para ello, sitúate en el escritorio (o donde quieras) y crea un fichero de texto plano. Dale cualquier nombre y ponle extensión ".udl".

 

http://qwalgrande.blogspot.es/img/udl_1.gif 

 

Luego hacer doble click sobre la udl y se abrirá un formulario en el que configurar la cadena de conexión. Rellena el proveedor (en la primera pestaña), el nombre del servidor, login, etc.

 

http://qwalgrande.blogspot.es/img/udl_2.gif 

 

Y por último, pulsas el botón "Test Connection" para comprobarla. Si lo deseas, luego puedes abrir el fichero resultante con notepad, por ejemplo, para ver qué cadena de conexión resulta. Ver esa cadena de conexión puede ser también de utilidad para resolver incidencias de este tipo.

 

http://qwalgrande.blogspot.es/img/udl_3.gif 

5ª Estrella

Escrito por qwalgrande 19-05-2010 en General. Comentarios (0)

Hoy he obtenido la quinta de las estrellas del sistema de reconocimiento del foro.

 

 http://qwalgrande.blogspot.es/img/Quinta_Estrella.jpg

 

No servirá para gran cosa, pero eso no significa que no me haga ilusión. Muchas gracias a todos los que valorais el esfuerzo de compartir lo poco que uno sabe con la comunidad.

Paginación con SQL Server: rápida, dinámica y eficaz

Escrito por qwalgrande 19-05-2010 en General. Comentarios (0)

Como había adquirido el compromiso de escribir un post sobre paginación, he estado revisando lo ya publicado (muchísimo sobre este tema en concreto). Hay muchas cosas interesantes, como ésta de Jesús López, pero muy pocas que me convenzan. Me gusta más la que yo uso habitualmente, lo que pasa es que es bastante compleja y dudo bastante del caracter pedagógico que pueda tener. Y tiene bastantes limitaciones en caso de que la consulta de partida sea algo complicada, por ejemplo, que use una agrupación. Además tampoco estoy 100% satisfecho con él, creo que es mejorable.

 

Y en esas, me he tropezado con este artículo:


http://www.4guysfromrolla.com/webtech/042606-1.shtml

 

Tiene dos cosas buenas. La primera es que se parece a mecanismo que yo uso en su concepto de no crear ninguna estructura temporal. La segunda, que aporta datos comparativos (y por supuesto favorables). Es un punto de vista diferente al de la mayoría, por eso considero oportuno revisarlo.

 

Yendo al método que me propongo compartir, una de sus virtudes es que pretende ser genérico: se la pasa la consulta. Esa es a su vez uno de sus peligros, usa sql dinámico para lograrlo, por lo obliga al que lo use a encapsular la llamada en otro procedimiento almacenado adicional para evitar la inyección de código. Y otra de sus virtudes, está para lo que está, es decir, paginar. Moverse unos registros hacia delante o hacia atrás, ir al primero bloque y al último. Pero no hace nada más. Ni recuentos, ni saber si en el último subconjunto de registros hay 5 ó 6 registros.

 

Se utilizan dos funciones para gestionar el problema de los campos de ordenación, que han de ser libres. Dicha ordenación, para ir a "SIGUIENTE" o "ANTERIOR", se consigue mediante uno de los parámetros que viene a cubrir la necesidad de "dame los 10 siguientes registros mayores a éste". Este campo se devuelve en el recorset y está para este fin, con lo que lo suyo es ocultarlo al cliente. Pero es clave para poder luego conseguir una paginación ordenada por los campos que se desee. Así, para llamar al "siguiente", tomas el último registro que te devolvió la anterior llamada y se lo pasas a esa.

 

Poco más queda por añadir (excepto el código):

 

CREATE function udf_Cadena_Entero(@pCadena varchar(3000), @pOrden varchar(4)) returns varchar(3000)

begin

declare @ret varchar(3000), @i tinyint

select @ret = '', @i = 1

while @i <= len(@pCadena)

begin

select @ret = @ret + case @pOrden when 'ASC' then cast(ascii(upper(substring(@pCadena, @i, 1))) as varchar(3)) else cast(255 - ascii(upper(substring(@pCadena, @i, 1))) as varchar(3)) end, @i = @i + 1

end

return @ret

end

GO

CREATE function udf_Format_OrderBy (@pCadena varchar(3000)) returns varchar(3000)

begin

declare @ret varchar(3000), @NombreCampo varchar(255), @tipo varchar(10), @ASC varchar(4), @pCad varchar(3000), @pos_coma int

select @ret = '', @pCadena = replace(@pCadena, ' ', ' ')

while len(@pCadena) > 0

begin

/*Quito la coma que pueda haber al inicio de la cadena*/

if left(ltrim(@pCadena), 1) = ','

select @pCadena = ltrim(right(ltrim(@pCadena), len(@pCadena) - 1))

/*Ubico la coma separadora de campos*/

select @pos_coma = case when charindex(',', @pCadena) = 0 then len(@pCadena) else charindex(',', @pCadena) end

/*tomo un conjunto de campo - tipo - orden y corto la cadena principal*/

select

@pCad = replace(substring(rtrim(@pCadena), 1, @pos_coma), ',', ''),

@pCadena = case when @pos_coma = len(@pCadena) then '' else substring(@pCadena, @pos_coma, len(@pCadena)) end

/*Asigno el campo, tipo y orden*/

select

@NombreCampo = substring(@pCad, 1, charindex(' ', @pCad) - 1),

@tipo = substring(@pCad, charindex(' ', @pCad) + 1, charindex(' ', @pCad, charindex(' ', @pCad) + 1) - charindex(' ', @pCad) - 1),

@ASC = substring(@pCad, charindex(' ', @pCad, charindex(' ', @pCad) + 1) + 1, len(@pCad))

/*Construyo la conversin*/

select @ret = @ret + case @tipo

when 'int' then 'COMUN.dbo.udf_Cadena_Entero(cast(replicate(''0'', 20 - len(cast(' + @NombreCampo + ' as varchar(40))))as varchar(40)) + cast(' + @NombreCampo + ' as varchar(40)), ''' + @ASC + ''') + '

when 'real' then 'COMUN.dbo.udf_Cadena_Entero(cast(replicate(''0'', 20 - len(cast(cast(' + @NombreCampo + '*10000 as int) as varchar(40))))as varchar(40)) + cast(' + @NombreCampo + ' as varchar(40)), ''' + @ASC + ''') + '

else 'COMUN.dbo.udf_Cadena_Entero(' + @NombreCampo + ', ''' + @ASC + ''') + ' end

end

/*Elimino el '+' final*/

select @ret = left (rtrim(@ret), len(@ret) -1)

return @ret

end

GO

/*Procedimiento de paginacin usando sp_executesql*/

/*

Parmetros:

- @pQuery: La consulta SIN la palabra SELECT

- @pOrden: Campos de la ordenacin con el formato "NombreCampo int/char asc/desc". Ejemplo: 'COD_USUARIO char asc'

- @pOrden_Valor: Valor para la paginacin, es el campo Ord del recordset devuelto. Si la opcin es PRIMERO o ULTIMO, este campo se ignora

- @pAntPosPriUlt: Navegacin, ha de valer PRIMERO, SIGUIENTE, ANTERIOR o ULTIMO.

- @pTop: Registros por consulta. Por defecto, vale 10.

- @pDistinct: Si es un select distinct... Se especifica aqu esa partcula (recordar que la query empieza con los nombres de los campos, "select", "top", "distinct" se especifican por otras vas, como sta).

- @pRev_Result: Permite que se le d la vuelta al recordset que se devuelve. til para la navegacin al ltimo o al anterior, que por defecto viene invertida

- @pDatabase: Nombre de la base de datos en la que se ejecuta la consulta.

ejemplo de llamada:

exec p_General_Paginado N'* from sysindexes where rowcnt > 900', 'rowcnt int asc', '', 'PRIMERO', 10, N'', 1, 'msdb'

*/

CREATE procedure [dbo].[p_General_Paginado]

@pQuery nvarchar(max),

@pOrden varchar(3000),

@pOrden_Valor varchar(3000),

@pAntPosPriUlt varchar(10),

@pTop int= 10,

@pDistinct nvarchar(8) = N'',

@pRev_Result bit = 0,

@pDatabase sysname = null

AS

set transaction isolation level read uncommitted

declare @cad nvarchar(max), @cad_red nvarchar(max), @Orden_cast nvarchar(max)

if charindex('where', @pQuery) = 0

begin

Raiserror ('La consulta no contiene "where".', 1, 1)

return -998

end

select @Orden_cast = dbo.udf_Format_OrderBy(@pOrden), @pDatabase = isnull(@pDatabase, db_name())

select @cad = N'SELECT ' + @pDistinct + N' top ' + cast(@pTop as nvarchar(12)) + N' ' + @Orden_cast + N' as Ord,' + @pQuery

/*Paginacin*/

if upper(@pAntPosPriUlt) = 'PRIMERO'

select @cad = @cad + N' ORDER BY Ord'

else if upper(@pAntPosPriUlt) = 'ULTIMO'

select @cad = @cad + N' ORDER BY Ord desc'

else if upper(@pAntPosPriUlt) = 'SIGUIENTE'

select @cad = @cad + N' and ' + @Orden_cast + N'>@Orden ORDER BY Ord'

else if upper(@pAntPosPriUlt) = 'ANTERIOR'

select @cad = @cad + N' and ' + @Orden_cast + N'<@Orden ORDER BY Ord desc'

/*Por ltimo se ejecuta sp_executesql*/

if @pRev_Result = 1 -- se han pedido los ltimos del recordset o los anteriores y hay que darle la vuelta al recordset

select @cad ='select * from (' + @cad + ') V order by 1'

select @cad_red = N'set transaction isolation level read uncommitted; USE ' + @pDatabase + ';' + replace(replace(replace(@cad, char(13) + char(10), ' '),' ', ' '),', ', ',')

--print @cad_red

exec sp_executesql @cad_red, N'@Orden varchar(300) ', @pOrden_Valor

return 0

GO

 


No sirve para todos los casos, pero sí para muchos y seguro que cada uno puede darle su toque personal y adaptarlo. También podéis compararlo con métodos más al uso, como row_number o incluso paginar en el cliente (que aún hay gente que lo hace a estas alturas).