39 votes

Emulate MySQL LIMIT clause dans Microsoft SQL Server 2000

Lorsque j'ai travaillé sur le Zend Framework composant de base de données, nous avons essayé de résumé de la fonctionnalité de l' LIMIT clause supportés par MySQL, PostgreSQL et SQLite. Qui est, la création d'une requête pourrait être fait de cette façon:

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

Lorsque la base de données prend en charge LIMIT, ce qui produit une requête SQL comme suit:

SELECT * FROM mytable ORDER BY somecolumn LIMIT 10, 20

Cela a été plus complexe pour les marques de base de données qui ne permettent pas d' LIMIT (cette clause ne fait pas partie de la norme SQL de la langue, par la voie). Si vous pouvez générer des numéros de ligne, faire de l'ensemble de la requête d'une table dérivée, et dans la requête externe utiliser BETWEEN. C'était la solution pour Oracle et IBM DB2. Microsoft SQL Server 2005 a une semblable ligne-numéro de la fonction, on peut donc écrire la requête de cette façon:

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;

Toutefois, Microsoft SQL Server 2000 n'a pas l' ROW_NUMBER() fonction.

Donc ma question est, pouvez-vous trouver un moyen pour émuler l' LIMIT de fonctionnalités dans Microsoft SQL Server 2000, uniquement à l'aide de SQL? Sans l'aide de curseurs ou T-SQL ou une procédure stockée. Il a à soutenir à la fois les arguments pour LIMIT, les deux nombre et de décalage. Les Solutions à l'aide d'une table temporaire ne sont pas acceptables.

Edit:

La solution la plus courante pour MS SQL Server 2000 semble être comme celui ci-dessous, par exemple, pour obtenir les lignes 50 à 75:

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

Toutefois, cela ne fonctionne pas si le jeu de résultats total est, disons 60 lignes. L'intérieur de la requête retourne 60 lignes parce que c'est dans le top 75. Alors que l'extérieur de la requête renvoie des lignes 35-60, qui ne rentre pas dans la "page" de 50 à 75. Fondamentalement, cette solution fonctionne, sauf si vous avez besoin de la dernière "page" d'un ensemble de résultats qui n'arrive pas à être un multiple de la taille de la page.

Edit:

Une autre solution fonctionne mieux, mais seulement si vous pouvez assumer le résultat inclut une colonne unique en son genre:

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

Conclusion:

Aucune solution ne semble exister pour l'émulation LIMIT de MS SQL Server 2000. Une bonne solution existe si vous pouvez utiliser l' ROW_NUMBER() fonction dans MS SQL Server 2005.

26voto

Brent Ozar Points 9067

J'ai déjà vu cette question de la part de clients et c'était la meilleure explication que j'ai vue de vos options et de leurs impacts:

http://www.codeproject.com/KB/aspnet/PagingLarge.aspx

5voto

Florian Points 1903

Voici une autre solution qui ne fonctionne que dans SQL Server 2005 et versions ultérieures, car elle utilise l'instruction except. Mais je le partage quand même. Si vous voulez obtenir les enregistrements 50 - 75, écrivez:

 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
 

0voto

user277498 Points 1129

Je voudrais essayer d'implémenter cela dans mon ORM car c'est assez simple là-bas. S'il faut vraiment que ce soit dans SQL Server, je regarderais le code généré par linq to sql pour l'instruction linq to sql suivante et partirai de là. L'ingénieur MSFT qui a implémenté ce code faisait partie de l'équipe SQL depuis de nombreuses années et savait ce qu'il faisait.

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

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X