transact limite index from sql mysql sql-server zend-framework

limite - Emular la cláusula LIMIT de MySQL en Microsoft SQL Server 2000



sql server rowcount (4)

Cuando trabajé en el componente de base de datos de Zend Framework , traté de abstraer la funcionalidad de la cláusula LIMIT soportada por MySQL, PostgreSQL y SQLite. Es decir, crear una consulta podría hacerse de esta manera:

$select = $db->select(); $select->from(''mytable''); $select->order(''somecolumn''); $select->limit(10, 20);

Cuando la base de datos admite LIMIT , produce una consulta SQL como la siguiente:

SELECT * FROM mytable ORDER BY somecolumn LIMIT 10, 20

Esto fue más complejo para las marcas de bases de datos que no admiten LIMIT (esa cláusula no es parte del lenguaje SQL estándar, por cierto). Si puede generar números de fila, haga que toda la consulta sea una tabla derivada, y en la consulta externa use BETWEEN . Esta fue la solución para Oracle e IBM DB2. Microsoft SQL Server 2005 tiene una función de número de fila similar, por lo que uno puede escribir la consulta de esta manera:

SELECT z2.* FROM ( SELECT ROW_NUMBER OVER(ORDER BY id) AS zend_db_rownum, z1.* FROM ( ...original SQL query... ) z1 ) z2 WHERE z2.zend_db_rownum BETWEEN @offset+1 AND @offset+@count;

Sin embargo, Microsoft SQL Server 2000 no tiene la función ROW_NUMBER() .

Entonces mi pregunta es, ¿pueden encontrar una manera de emular la funcionalidad LIMIT en Microsoft SQL Server 2000, utilizando únicamente SQL? Sin usar cursores o T-SQL o un procedimiento almacenado. Tiene que admitir ambos argumentos para LIMIT , tanto count como offset. Las soluciones que usan una tabla temporal tampoco son aceptables.

Editar:

La solución más común para MS SQL Server 2000 parece ser la siguiente, por ejemplo, para obtener las filas 50 a 75:

SELECT TOP 25 * FROM ( SELECT TOP 75 * FROM table ORDER BY BY field ASC ) a ORDER BY field DESC;

Sin embargo, esto no funciona si el conjunto de resultados total es, digamos 60 filas. La consulta interna devuelve 60 filas porque está en el top 75. Luego, la consulta externa devuelve las filas 35-60, que no cabe en la "página" deseada de 50-75. Básicamente, esta solución funciona a menos que necesite la última "página" de un conjunto de resultados que no sea un múltiplo del tamaño de la página.

Editar:

Otra solución funciona mejor, pero solo si puedes asumir que el conjunto de resultados incluye una columna que es única:

SELECT TOP n * FROM tablename WHERE key NOT IN ( SELECT TOP x key FROM tablename ORDER BY key );

Conclusión:

No parece existir una solución de propósito general para emular LIMIT en MS SQL Server 2000. Existe una buena solución si puede usar la función ROW_NUMBER() en MS SQL Server 2005.


Aquí hay otra solución que solo funciona en Sql Server 2005 y posterior porque usa la declaración except. Pero lo comparto de todos modos. Si quiere obtener los registros 50 - 75, escriba:

select * from ( SELECT top 75 COL1, COL2 FROM MYTABLE order by COL3 ) as foo except select * from ( SELECT top 50 COL1, COL2 FROM MYTABLE order by COL3 ) as bar


Cuando solo necesita LIMIT, ms sql tiene la palabra clave TOP equivalente, por lo que es claro. Cuando necesite LIMIT con OFFSET, puede probar algunos hacks como se describió anteriormente, pero todos agregan algo de sobrecarga, es decir, para ordenar de una manera y luego de la otra, o de la operación NOT IN de gasto. Creo que todas esas cascadas no son necesarias. La solución más limpia en mi opinión sería simplemente usar TOP sin compensación en el lado de SQL, y luego buscar el registro de inicio requerido con el método de cliente apropiado, como mssql_data_seek en php. Si bien esta no es una solución pura de SQL, creo que es la mejor, ya que no agrega ningún sobrecarga (los registros salteados no se transferirán a la red cuando los busque, si eso es lo que le preocupa )


Intentaré implementar esto en mi ORM ya que es bastante simple allí. Si realmente necesita estar en SQL Server, entonces miraría el código generado por linq a sql para la siguiente instrucción linq a sql e iría desde allí. El ingeniero de MSFT que implementó ese código fue parte del equipo de SQL durante muchos años y sabía lo que estaba haciendo.

var result = myDataContext.mytable.Skip (pageIndex * pageSize) .Take (pageSize)


SELECT TOP n * FROM tablename WHERE key NOT IN ( SELECT TOP x key FROM tablename ORDER BY key DESC );