Paging su SQL Server 2005
Problema tipico: abbiamo un bel po’ di record da mostrare nella nostra applicazione (win e soprattutto web) e vogliamo paginarli per una migliore lettura. Approccio tipico - io per primo per fretta e non curanza lo applico spesso e volentieri - è quello di tirare su con una query tutti i record e poi lasciare che sia il nostro gridview a preoccuparsi del paging.
Evidente problema di questo approccio: se i record sono tanti le performance diventano imbarazzanti. Ad ogni cambio di pagina infatti vengono inviati tutti i dati per poi visualizzarne una minima sottoparte.
Come detto, finchè sono pochi record si può lasciare anche così, ma se il numero sale (e non c’è neppure bisogno salga tanto invero) bisogna far qualcosa per migliorare le performance.
Soluzione: paginare sul database via sql.
Detto così pare banale, ma farlo su SQL Server non è mai stato molto semplice. Purtroppo in casa Microsoft non hanno ancora introdotto istruzioni tipo LIMIT di MySQL, ma in SQL Server 2005 hanno almeno introdotto il comando ROW_NUMBER() che ci semplifica la vita.
Vediamo come lo si può sfruttare in combinazione con le Common Table Expressions (CTE).
Supponiamo di avere la seguente query da voler eseguire:
SELECT idPersona, nome, cognome, dataNascita, codiceFiscale, sesso
FROM Persone
ORDER BY idPersona
Ora facciamone una CTE:
WITH PagedPersone AS
(
SELECT idPersona, nome, cognome, dataNascita, codiceFiscale, sesso
FROM Persone
)
SELECT idPersona, nome, cognome, dataNascita, codiceFiscale, sesso
FROM PagedPersone
ORDER BY idPersona
Ovviamente il risultato è analogo.
Ora è il momento di ROW_NUMBER(). Per dettagli sull’istruzione vi rimando al MSDN: ROW_NUMBER (Transact-SQL).
WITH PagedPersone AS
(
SELECT idPersona, nome, cognome, dataNascita, codiceFiscale, sesso, ROW_NUMBER() OVER (ORDER BY idPersona) AS RowNumber
FROM Persone
)
SELECT idPersona, nome, cognome, dataNascita, codiceFiscale, sesso
FROM PagedPersone
ORDER BY idPersona
Anche in questo caso il risultato della query è lo stesso, ma ora in PagedPersone abbiamo anche un numero (RowNumber) incrementale che “conta” le tuple. A questo punto fare il paging diventa banale.
DECLARE @PageNumber int
DECLARE @PageSize int
SET @PageNumber = 10;
SET @PageSize = 20;WITH PagedPersone AS
(
SELECT idPersona, nome, cognome, dataNascita, codiceFiscale, sesso, ROW_NUMBER() OVER (ORDER BY idPersona) AS RowNumber
FROM Persone
)
SELECT idPersona, nome, cognome, dataNascita, codiceFiscale, sesso
FROM PagedPersone
WHERE RowNumber > ((@PageNumber - 1) * @PageSize) AND RowNumber <= (@PageNumber * @PageSize)
ORDER BY idPersona
Ecco dunque risolto il problema del paging. Testando la tecnica noterete quanto le performance migliorino.











mi sono imbattuto per caso in questo articolo, cercando su google come fare il paging a livello di DB…
e oltre aver trovato un modo semplice, ho imparato anche le CTE (che non conoscevo).. che dire… grazie!!
Comment by sstefano — January 13, 2008 @ 15:23
Mi fa piacere che ti sia risultato utile
Comment by Alessio — January 13, 2008 @ 18:37