Если вы пытаетесь реализовать пейджинг, это неправильно во многих отношениях. Во-первых, вы используете SET ROWCOUNT для ограничения @startRowIndex, но затем вы выбираете ВСЕ n строк (без ORDER BY), затем получаете первый идентификатор, а затем подсчитываете общее количество строк, выбирая из таблицы? Могу ли я предложить лучший подход?
CREATE PROCEDURE dbo.PageSmarter
@Table NVARCHAR(128), -- table names should not be varchar(20)
@FirstRow INT,
@PageSize INT,
@TotalRows INT OUTPUT
AS
BEGIN
SET NOCOUNT ON; -- always, in every stored procedure
DECLARE
@first_id INT,
@startRow INT,
@sql NVARCHAR(MAX);
SET @sql = N'WITH x AS
(
SELECT
ID,
rn = ROW_NUMBER() OVER (ORDER BY ID)
FROM
' + @Table + '
)
SELECT rn, ID
INTO #x FROM x
WHERE rn BETWEEN ' + CONVERT(VARCHAR(12), @FirstRow)
+ 'AND (' + CONVERT(VARCHAR(12), @FirstRow)
+ ' + ' + CONVERT(VARCHAR(12), @PageSize) + ' - 1);
SELECT first_id = MIN(ID) FROM #x;
SELECT
ID, StringID_from_Master, GUID, short_Text, lang_String, date_Changed,
prev_LangString, needsTranslation, displayRecord, brief_Descrip
FROM ' + @Table + ' AS src
WHERE EXISTS
(
SELECT 1 FROM #x
WHERE ID = src.ID
);';
EXEC sp_executeSQL @sql;
SELECT @totalRows = SUM(row_count)
FROM sys.dm_db_partition_stats
WHERE [object_id] = OBJECT_ID(@Table);
END
GO
DECLARE @tr INT;
EXEC dbo.PageSmarter 'dbo.tablename', 10, 2, @tr OUTPUT;
SELECT @tr;
Я не проверял все крайние случаи с этой конкретной реализацией. Признаюсь, есть гораздо лучшие способы сделать это, но они обычно не сложны с дополнительным требованием динамических имен таблиц. Это говорит о том, что с вашим дизайном что-то не так, если вы можете выполнять одинаковые запросы к любому количеству таблиц и получать схожие результаты.
В любом случае, вы можете просмотреть некоторые (довольно продолжительные) обсуждения различных подходов к подкачке в SQL Server Central:
http://www.sqlservercentral.com/articles/T-SQL/66030/
После статьи имеется 62 комментария:
http://www.sqlservercentral.com/Forums/Topic672980-329-1.aspx