Sergio Álvarez (xergio)

Escrito 457

MS SQL Server, bastante limitado

"Limitado" con doble sentido. Mucha gente defiende a capa y espada SQL Server. Yo antes pensaba que SQL Server (mssql para los amigos) no era TAN malo como decían, por lo que habría tratado con él en clase, con el administrador que lleva, etc. Nunca lo había usado en entornos de producción exhaustivos como ahora, ni tampoco me había enfrentado a problemas a la hora de rendimiento.

Bien, el caso de prueba es el siguiente, un simple paginador, por ejemplo a una tabla con 100 registros. Quiero los registros del 50 al 60.

Simplemente, no se puede. Algo tan sencillo como en MySQL o Postgre sería con un LIMIT 60, 10, aquí no se puede.

Es algo que hemos discutido hoy y se han propuesto soluciones: sacar los 100 registros y dejarlos en memoria, en $_SESSION, crear una tabla temporal y dejar ahí el resultados, hacer vistas que comprendan menos datos... todo ello poco escalable y extensible.

Y hablo con 100 registros, imaginemos miles, millones... Desde luego no me imagino a sitios como Yahoo!, Flickr, Twitter, del.icio.us, Digg, Meneame (por decir sitios que usan DBs como MySQL o Postgre) en los que le digas que quieres ver la página 100 de un listado y se tire 20 segundos cacheando resultados para que luego te vaya rápido, o guardando en memoria, ni nada de esas ñapas que habría que hacer con mssql.

Pero bueno, al menos con mssql hay un muy buen soporte técnico que en otros casos igual no tienes, y sabes los recursos que necestas para que todo vaya bien.

39 comentarios

 Jabber status Percewall comentó:

[Avatar]
  • #1
  • 18-5/00:17
Pues en oracle no es mucho mejor....

 Jabber status nils comentó:

[Avatar]
  • #2
  • 18-5/03:02
En Oracle creo que con poner WHERE ROWCOUNT = x te devolvia x resultados.

MS SQL nunca lo he usado, pero si he tenido que tocar algo con las bases de datos de Access accediendo desde VBA en Excel y no hay manera de limitar los resultados de forma cómoda. Es un tema que también he comentado con algunos compañeros del curro y están todo deacuerdo en que la función LIMIT es algo imprescindible, ya que realmente facilita el trabajo...

dan comentó:

  • #3
  • 18-5/08:38
Una tabla temporal si utilizas Sql Server 2000, tampoco creo que sea algo tan catastrófico. Si es la versión 2005, más fácil con las common table expressions ( CTE ).

La implementación para la versión 2000 ( también válida para 2005 ) es esta: http://jdixon.dotnetdevelopersjournal.com/paging_resultsets_in_sql_2000_and_sql_2005.htm

Siempre son los mismos pasos para paginar registros, copy-paste y a otra cosa.

 Jabber status x****o comentó:

[Avatar]
  • #4
  • 18-5/09:21
Igualmente... es una locura tener que andar con esos lios para una simple paginación, no creeis?

Sigo viéndo un atraso.

 Jabber status ZiTAL comentó:

[Avatar]
  • #5
  • 18-5/09:22
Navegando por internet me tope con este post de xergio donde me entero que algo tan imprescindible como limit en mysql, en microsoft sql server no se puede hacer.

via: http://xergio.net  

Ruben comentó:

  • #6
  • 18-5/09:54
en SQL Server existe el TOP que es igual que el limit.

 Jabber status ZiTAL comentó:

[Avatar]
  • #7
  • 18-5/10:56
Al parecer tiene limite de registros pero no tiene la opcion de elegir DESDE que registro empezar.

Nogiv comentó:

  • #8
  • 18-5/14:08
Cómo puede alguien -que, supuestamente, entiende algo de ésto- siquiera comparar SQL Server con MySQL o Postgre y quedarse tan tranquilo...

Gijón comentó:

  • #9
  • 18-5/16:51
  Lo que hay que oir a veces...

  Soltar que SQL Server es "limitado" por éso de la paginación, comparándolo alegremente con MySQL y PostgreSQL, es como decir que un Ferrari 599 GTB es "limitado" porque no tiene radiocassette, pero que tu Renault 5 sí lo tiene. De acuerdo, efectivamente, el Ferrari 599 GTB no incluye radiocassette, pero su motor es un 6.000cc V12 de 620CV. Tu comentario me parece un excelente ejemplo de lo que se suele llamar "mear fuera del tiesto"

  Por cierto, no está de más leer un poco antes de soltar gilip*lleces, échale un vistazo al siguiente artículo:

  ROW_NUMBER (Transact-SQL)   http://msdn2.microsoft.com/en-us/library/ms186734.aspx

 Jabber status xergio comentó:

[Avatar]
  • #10
  • 18-5/17:29
Rubén, el TOP no es lo mismo que el LIMIT, no tiene offset.

Nogiv, igual porque conozco las dos partes y me he tenido que pelear con cosas de mssql que en otro sistema es trivial.

Gijón, el ROW_COUNT es perfecto si usas SQL Server 2005, pero no tenemos ese placer.

Gilipolleces las justas, me parece perfecto que defendais a muerte mssql porque adorais M$, su filosofía, y todo es chachi piruli, pero con cualquier otro sistema jamás me he tenido que pasar un día un medio buscando la forma de hacer una simple paginación como este caso.

Además no hablo solo de este tema, he mencionado este proque ayer se nos dió el caso de que con tan solo 100mil registros nos tardaba en devolver el resultado (sin, indexado todito y con una páquina que va sobrada), pero si quieres hago un recopilatorio de LAS COSAS que le faltan y el resto de sistemas tienen desde hace años.

Hay empresas o procesos con más carga de datos de los que jamás veremos muchos y usan esos sistemas que tanto desprestigiais como MySQL o Postgres y que funcionan SIN UN SOLO PROBLEMA, ya me gustaría ver cómo funcionaban con mssql ;)

De todos modos hemos encontrado una ñapa que va bastante bien para nuestro cometido. Es increible que yaha que usar algo así para hacer algo TAN SENCILLO: http://weblogs.sqlteam.com/jeffs/archive/2004/03/22/1085.aspx

Y aquí nuestra versión parcheada porque fallaba con ordenaciones múltiples:

set ANSI_NULLS ON
set QUOTED_IDENTIFIER ON
go

-- paginate 'select * from messages', 'id DESC', 100000, 100010

ALTER PROCEDURE [dbo].[Paginate](@Select VARCHAR(5000),
@OrderBy VARCHAR(1000),
@StartRow INT,
@EndRow INT)
AS
BEGIN

DECLARE @ColList VARCHAR(5000);
DECLARE @Where VARCHAR(5000);
DECLARE @i INT;
DECLARE @i2 INT;
DECLARE @tmp VARCHAR(1000);
DECLARE @dec VARCHAR(1000);
DECLARE @f VARCHAR(100);
DECLARE @d VARCHAR(100);
DECLARE @Symbol CHAR(2);
DECLARE @NullBoundaryCheck VARCHAR(1000);
DECLARE @SQL VARCHAR(8000);
DECLARE @Sort VARCHAR(1000);

SET @Sort = @OrderBy + ', '
SET @dec = ''
SET @Where = ''
SET @SQL = ''
SET @i = CHARINDEX(',' , @Sort)

WHILE @i != 0
BEGIN
SET @tmp = LEFT(@Sort, @i-1)
SET @i2 = CHARINDEX(' ', @tmp)
SET @f = LTRIM(RTRIM(LEFT(@tmp, @i2-1)))
SET @d = LTRIM(RTRIM(SUBSTRING(@tmp, @i2+1, 1000)))
SET @Sort = RTRIM(LTRIM(SUBSTRING(@Sort, @i+1, 1000)))
SET @i = CHARINDEX(',', @Sort)
SET @symbol = CASE WHEN @d = 'ASC' THEN '>' ELSE '<' END +
CASE WHEN @i = 0 THEN '=' ELSE '' END
SET @NullBoundaryCheck = CASE WHEN @i = 0
THEN CASE WHEN @d = 'ASC' THEN '@' ELSE '' END + @f + ' IS NULL'
ELSE
'@' + @f + ' IS ' + CASE WHEN @d = 'DESC' THEN '__NOT__' ELSE '' END + ' NULL AND ' +
@f + ' IS ' + CASE WHEN @d = 'ASC' THEN '__NOT__' ELSE '' END + ' NULL'
END
SET @dec = @dec + 'DECLARE @' + @f + ' SQL_VARIANT; '

PRINT 'n' + @ColList + 'n'

SET @ColList = 
CASE WHEN 
REPLACE(REPLACE(REPLACE(@colList, '>','='), '<','='), '__NOT__', '') IS NULL
THEN ''
ELSE
REPLACE(REPLACE(REPLACE(@colList, '>','='), '<','='), '__NOT__', '') + ' AND '
END + '((@' + @f + ' IS NOT NULL AND ' + @f + ' IS NOT NULL AND ' + @f + @Symbol + '@' + @f + ') OR (' + @NullBoundaryCheck + '))'

SET @Where = @Where + ' OR (' + @ColList + ') '
SET @SQL = @SQL + ', @' + @f + '= ' + @f
--PRINT @COLLIST
--PRINT @WHERE
--PRINT @SQL
END
SET @Where = REPLACE(@Where, '__NOT__', 'NOT')
SET @SQL = @dec + ' ' +
'SET ROWCOUNT ' + CONVERT(VARCHAR(10), @StartRow) + '; ' +
'SELECT ' + SUBSTRING(@SQL,3,7000) + ' FROM (' + @Select + ') A ORDER BY ' +
@OrderBy + '; ' +
'SET ROWCOUNT 0;' +
'SELECT TOP ' + CONVERT(VARCHAR(10), (1 + @EndRow - @StartRow)) + ' * FROM (' + @Select + ') A WHERE ' +
SUBSTRING(@Where,4,7000) + ' ORDER BY ' + @OrderBy + '; '
--PRINT @WHERE
PRINT @SQL
EXEC (@SQL)
END

Y una cosa muy importante: mysql 5 no es para nada lo qeu era mysql 3.23, y postgres 8 lo que era postgres 7. Hay que renovar eas mentalidad...

Saludos.

Gijón comentó:

  • #11
  • 18-5/18:55
>> el ROW_COUNT es perfecto si usas SQL >> Server 2005, pero no tenemos ese placer

Entonces, yo también podría decir que MySQL es «bastante limitado» porque no tiene procedimientos almacenados. Y, claro, tú me dirías "Claro que los tiene, en la versión 5.0" Y yo te diría "Pero no tenemos ese placer, usamos la 4.1"

>> me parece perfecto que defendais a muerte mssql >> porque adorais M$, su filosofía, y todo es chachi piruli

Yo no defiendo a muerte a Microsoft, ni mucho menos. Microsoft no me da de comer, pero "facilita" mucho mi trabajo (que sí me da de comer). Y, además, estoy harto de lidiar con los talibanes de Linux. A ver qué día comienzan [comenzáis] a distinguir entre el mundo real y el maravilloso universo de bondad y felicidad que imagináis

>>Hay empresas o procesos con más carga de datos >>de los que jamás veremos muchos y usan esos >>sistemas que tanto desprestigiais como MySQL o Postgres

Para aclarar éstas cosas están las pruebas objetivas y las estadísticas. Por ejemplo, échale un vistazo a los 10 primeros puestos de http://www.tpc.org

>>mysql 5 no es para nada lo qeu era mysql 3.23 >>y postgres 8 lo que era postgres 7 >>Hay que renovar eas mentalidad...

Por supuesto que no. Pero tampoco SQL Server 2005 es lo que era SQL Server 6.5, ni Windows XP es lo que era Windows 3.11 Claro que hay que cambiar la mentalidad, pero tenemos que cambiarla TODOS

Un saludo desde Gijón

 Jabber status xergio comentó:

[Avatar]
  • #12
  • 18-5/22:31
Gijón, ok, entonces el único error que he cometido para ti es no haber especificado en la versión de mssql. Yo hablaba de la 2000, la que tiene la mayoría de la gente. Si quieres solucionar algunos preblas de la versión 2000 hay que gastarse una pasta gansa y migrar a 2005. Ains... si todo fuera así de sencillo...

"pero "facilita" mucho mi trabajo": mmmm precisamente ese es el motivo central de mi queja, que me hace perder tiempo :) Me dirás que no sé de mssql, pero es que el ejemplo que he puesto de la paginación se lo he planteado a gente que si sabe, incluso he buscado por la red, y nadie tenía soluciones eficaces.

"distinguir entre el mundo real y el maravilloso universo de bondad y felicidad que imagináis": qué mundo es ese? La verdad es que yo tampoco voy a discutir xD pero ya es triste que el mundo real sea vuestro mundo, es muy triste... y lo es más decir que "todo lo que no es de pago" es malo o de hackers :)

Respecto a lo de TPC: todo sistemas propietario y la gran mayoría Oracle, los que no db2 o mssql (la solución barata a sistemas propietario). Ojo, no estoy en contra de usar oracle, mssql o db2, si tienes un problema pegas un telefonazo, sueltas la pasta y te lo arreglan. Eso para las empresas va muy bien... "ahorra" tiempo a sus empleados :) (ese es el mundo real al que re referías?)

Un saludo desde Madrid.

Zhivago comentó:

  • #13
  • 19-5/13:20
Paginación con SQL-Server 2000 creando tabla temporal.

Select Cast([ProductID as int) As ProductID, [Name], [ProductNumber], RowNum = Identity(int,1,1) into #newTable From [Product]

Select * From #newTable Where RowNum Between @startNumber and (@startNumber + @MaxNumber)

Drop Table #newTable

Saludos

 Jabber status nils comentó:

[Avatar]
  • #14
  • 19-5/13:24
No conozco MS SQL SERVER ese, pero hay que reconocer que gracias a MySQL y demás herramientas del software libre se acerca a mucha gente a estas herramientas. Es como Windows, acerca a la gente al mundo de la informatica, que si quieren más, pues se meten en sistemas mas complejos como Unix.

Yo he trabajado con MySQL y Oracle y hay cosas queme gustan de MySQL que Oracle no tiene y hay cosas de Oracle que me gustan que MySQL no tiene.

De todas formas, siempre se puede programar un poco y conseguir los mismos resultados. Aunque es cierto que la función LIMIT de MySQL es algo muy útil y que no veo el mótivo por el cual no lo implementen en los demás motores de Bases de Datos.

Un saludo desde Berlin :)

Zeru comentó:

  • #15
  • 21-5/17:21
Que yo recuerde Limit no es parte del standar sql-92. Es decir creo que no se debe criticar a MS-SQLServer ni a ninguna otra DB por no incluir el comando Limit, por ejemplo Oracle y PostgreSQL no lo soportan.

Pero... MS-SQLServer es una basura por muchas otras razones.

 Jabber status Vairon comentó:

[Avatar]
  • #16
  • 15-6/02:09
Zeru creo que deberias de decir las razones por las cuales osas a decir que "es una basura por muchas otras razones" y no dar los motivos o razones del por que como otras personas que al menos tienen argumentos de lo que dices asi que te sugiero que dejes a los grandes hacer lo que saben hacer

Marcos comentó:

  • #17
  • 25-7/20:36
USE [dbx] GO

SET ANSI_NULLS ON GO SET QUOTED_IDENTIFIER ON GO

CREATE PROCEDURE Pagina     @Table        VARCHAR(128)    = NULL,     @Filter        VARCHAR(1024)    = NULL,     @OrderBy    VARCHAR(128)    = NULL,     @PageIndex    INTEGER            = 0,     @PageSize    INTEGER            = 0 AS BEGIN

DECLARE @Filter2 AS VARCHAR(1024); SET @Filter2 = '';

IF @OrderBy IS NOT NULL BEGIN     SET @OrderBy = ' ORDER BY ' + @OrderBy; END ELSE BEGIN     SET @OrderBy = ' ORDER BY id'; END

IF @Filter IS NOT NULL BEGIN     SET @Filter2 = ' WHERE ' + @Filter;     SET @Filter = ' AND ' + @Filter; END

EXEC ( '     SELECT         *   FROM

   (      SELECT         ROW_NUMBER() OVER(' + @OrderBy + ') AS RowNum                 , t.*      FROM ' + @Table + ' AS t ' + @Filter2 + '    ) AS main    WHERE RowNum BETWEEN ((' + @PageIndex + ' - 1) * ' + @PageSize + ' + 1) AND (' + @PageIndex + ' * ' + @PageSize + ') ' ) END

Sebenscen comentó:

  • #18
  • 16-8/03:07
He aqui la solucion por la que todos se descabezan busquen mas y no se quejen tanto que si miramos motor por motor todos son excelentes.

DECLARE @rowA INT DECLARE @rowB INT SET @rowA = 5 SET @rowB = 10 SELECT TOP (@rowA+1)   id_comentario,   autor_comentario FROM   (    SELECT TOP (@rowB)     id_comentario,     autor_comentario    FROM     comentarios    ORDER BY     id_comentario   ) i ORDER BY   id_comentario DESC

ar7uro comentó:

  • #19
  • 3-9/18:37
sergio oracle y mssql son las unicas bases de datos existentes serias, las demas son juguetitos. en serio, no puedes comparar mssql con mysql, ni word con wordpad y mucho menos "C++" con "Logo".

Tu diras pero en "Logo" es mas facil dibujar una linea, pero definitivamente sabemos que C++ es mejor, ¿o no?

A nadie se le ocurre comparar mssql con mysql. No quiero ser mala onda, ni mucho menos burlon, pero quedas mal con comentarios asi. Disculpa si mi opinion te ofende.

Sobre cual es mejor: ORACLE o MSSQL, ahi si, entremos a discutir.

chao, saludos

ar7uro comentó:

  • #20
  • 3-9/18:46
"Y, además, estoy harto de lidiar con los talibanes de Linux. A ver qué día comienzan [comenzáis] a distinguir entre el mundo real y el maravilloso universo de bondad y felicidad que imagináis"

LO MAXIMO GIJON!!! :)

 Jabber status xergio comentó:

[Avatar]
  • #21
  • 3-9/22:04
Y porqué yahoo ysa mysql en su buscador y va rápido? y porqué digg usa mysql? o meneame? si es taaaan malo, porqué a ellos les va bien? y porqué los uqe usan mssql necesitan máquinas de la leche para que vayan bien? :)

Seguro que yo quedo mal afirmando que mssql tiene limitaciones? xD

Toni B. comentó:

  • #22
  • 15-9/20:03
Muy buenas a todos. En vista de esta miniguerra que está habiendo entre distintos servicios de SQL, quiero añadir algo:

Microsoft 'loquesea' es de ¡PAGO! Ya sabéis, licencias y tal. Microsoft compartió con Sybase el trabajo (o sea, trabajaba la última), por lo que su base de datos fue MUY BUENA hasta la 6.5, cuando todavía la manejaban entre ambos. Versiones a partir de la 7 eran puramente de Microsoft y no son malas, pero en fin, conocemos a éstos y no hace falta decir lo que hacen con los estándares y con el mercado, ¿no?

MySQL y PostgreSQL son unas alternativas libres que, cuando las pruebas y ves cómo funcionan -si importas base de datos y funcionan-, no te hace falta volver al MSSQL. Y quien ordena y manda apenas usa la interfaz gráfica bonita. ¿¿Y pa qué tanto cilindro y Cv, si sólo ha de viajar un trozo de carne/consulta?? Lo que cuenta no es la máquina, sino el manejo y metodología de búsqueda. Prefiero un Seat Toledo rapidillo de 5 plazas que no un biplaza de 500Cv.

Oracle: No quiero decir nada sobre la mejor y más cara del mundo.

Pd: No os metáis con los linuxeroos que van a más, aunque MS ""expresse"" sus programas (jajaja)

MR MSSQL comentó:

  • #23
  • 11-2/03:50
MYSQL ES B-A-S-U-R-A por donde la veas Si alguien la usa es poque no tiene dinero o es demasiado mezquino para comprar Oracle o MSSQL, cuantas empresas usan mysql? cuantas usan mssql? cuantas usan oracle? entonces todos estan mal por pagar y deben usar mysql? es B-A-S-U-R-A

Gabo comentó:

  • #24
  • 4-3/14:33
Mirá, yo estoy cansado de maldecir los productos de Micro$oft por deficiencias o errores que no deberían tener los productos de una empresa como esa... Aún así, en este momento me estoy encontrando con el mismo problema que planteás, pero creo que "NO SE PUEDE" no es una respuesta en este caso, si no se pudiera hacer eso no lo hubieran vendido el servidor de bases de datos a NADIE, debe haber alguna forma... Seguro que es un quilombo, pero que la hay... seguro que la hay.

Saludos.  

 Jabber status Kristel comentó:

[Avatar]
  • #25
  • 5-3/04:29
Ne sar

 Jabber status Scott comentó:

[Avatar]
  • #26
  • 14-3/12:07
Partito http://www.plastprintpack.com/comune-napoli-it suo,.

 Jabber status Karen comentó:

[Avatar]
  • #27
  • 15-3/05:11
De ha <a href='http://www.tizakiform.com/canale' >canale invece.

 Jabber status Karen comentó:

[Avatar]
  • #28
  • 15-3/05:11
Stato in <a href='http://www.tizakiform.com/canale' >come canale.

 Jabber status Juan comentó:

[Avatar]
  • #29
  • 15-3/18:59
Fine fare <a href='http://www.tizakiform.com/ragazza-single' >la ragazza single,.

 Jabber status Mark comentó:

[Avatar]
  • #30
  • 16-3/09:55
Cui http://www.celebrateliterarybelfast.com/voli-nazionali detto.

Deja un comentario

Pulsa en los títulos para ver información sobre cómo comentar.

Autocompletado de nicks

Todos los campos del formulario son opcionales menos el del PIN.

Usa el tabulador para autocompletar los nicks de otros comentaristas.

Si escribes @ y pulsas la tecla tabulador varias veces podrás recorrer la lista de nicks usados

Y si escribes # (almoadilla) y número (Ej.: #5) se substituirá directamente el nick del comentario correspondienmte al pulsar el tabulador.

Tags HTML permitidos

Tags: a, strong, b, em, u, code, cite.

El tag a admite la propiedad href="..." para indicar la dirección.

Los tags también tienen autocompletado (al igual que los nicks). Para usarlos se pone por ejemplo strong + TABULADOR.

Formulario para comentar

Cargando...

Todo el contenido bajo el dominio XERGIO.NET está sujeto a la licencia Creative Commons con las condiciones BY-SA. Web estandarizada en XHTML 1.0, CSS 2, RSS 2 y Atom 1.0.