|
Программирование >> Программирование баз данных
SQL Sewer обычно предоставляют также возможность организовать обработку данных с помощью операций над множествами, ведь именно для этого и предназначены реляционные СУБД, такие как SQL Server. А что касается курсоров на основе API-интерфейсов, то с их помощью может осуществляться только построчная обработка данных, поэтому, в отличие от курсоров SQL Server, не приходится задумываться над тем, следует ли применять в серверном приложении операции построчной обработки или операции над множествами, поскольку предусмотрены только первые. С другой стороны, в клиентском приложении допускается применение пюлько операций построчной обработки данных с использованием курсоров, поэтюму именно на это и следует рассчитывать. Иными словами, для обеспечения вьхакой производительности многоуровневой системы, в состав которой входят клиенпижое и серверное приложения, следует отказаться от использования курсоров в серверном компоненте, если этю возможно. Срок существования курсора Чтобы изложить достаточно подробно тематику, связанную с курсорами, необходимо привести большое количество разнообразных сведений, поэтому, вероятно, следует начать с изучения наиболее простой разновидности курсора, а затем на ее основе перейти к более детальному описанию. Но прежде чем перейти к рассмотрению фактически применяемого синтаксиса, необходимо отметить, что в процессе работы с курсорами приходится использовать не один, а несколько операторов. Основные этапы процесса использования курсора перечислены ниже. Объявление. Открытие. Использование/ перемещение по строкам. Закрытие. Освобождение. Таким образом, основная синтаксическая структура оператора объявления курсора выглядит следующим образом: DECLARE <cursor name> CURSOR FOR <select statement> Следует учитывать, что разработчик всегда может прибегнуть к использованию такого чрезвычайно упрощенного подхода: создавать курсор, широко используя значения, предусмотренные по умолчанию. Примеры более сложных объявлений курсоров будут рассматриваться в данной главе немного позже. Имя курсора полностью аналогично любому другому имени переменной, поэтому должно соответствовать правилам именования, принятым в СУБД SQL Server, не считая того, что в имени курсора не предусмотрен префикс @. В качестве оператора SELECT может применяться любой допустимый оператор SELECT, который возвращает результирующий набор. Однако необходимо учитывать, что некоторые результирующие наборы не будут обновляемыми. (Например, если используется конструкция GROUP BY, то возникает неопределенность в отношении того, какая часть группы должна быть обновлена. По аналогичной причине сказанное относится и к вычисляемому полю.) Продолжим рассмотрение данной темы и выполним довольно простой пример. На этом этапе мы не сможем использовать приведенный пример достаточно широко, но ниже будет показано, что он способен стать основой довольно удобного инструментального средства управления индексами. DECLARE ©SchemaName varchar(255) DECLARE ©TableName varchar(255) DECLARE ©IndexName varchar(255) DECLARE ©Fragmentation float DECLARE TableCursor CURSOR FOR SELECT SCHEMA NAME(CAST(OBJECTPROPERTYEX(i.object id, Schemald) AS int)), OBJECT NAME(i.obj ect id) , i.name, ps. avg f ragmentation in j)ercent FROM sys.dm db index j)hysical stats (DB ID(), NULL, NULL, NULL, NULL) AS ps JOIN sys.indexes AS i ON ps.object id = i.object id AND ps.index id = i.index id WHERE avg fragmentation in percent > 3 0 Необходимо отметить, что и этот пример не дает полного представления обо всех возможностях курсоров. Одной из основных особенностей курсоров, которая сразу же бросается в глаза, является то, что применяемые в них операторы SELECT содержат больший объем кода по сравнению с обычными операторами SELECT. В приведенном примере был объявлен курсор TableCursor, основанный на операторе SELECT, с помощью которого осуществляется выборка данных из всех таблиц в рассматриваемой базе данных. Кроме того, объявлена переменная, предназначенная для временного хранения данных, в которой будут содержаться значения полей текущей строки во время работы с курсором. После объявления курсора его необходимо открыть: OPEN TableCursor При открытии курсора фактически выполняется запрос, заданный в конструкции FOR, и с этого момента можно приступать к работе с курсором. Для этого необходимо осуществить следующие действия. Получить с помощью оператора FETCH первую строку. По мере необходимости провести обработку в цикле остальных строк с помощью оператора FETCH. Рассмотрим, каким должен быть первый оператор FETCH, в котором приведены указания, необходимые для получения конкретной строки. В этом операторе необходимо также указать, в какие переменные следует поместить полученные значения: FETCH NEXT FROM TableCursor INTO ©TableName, ©IndexName, ©Fragmentation После выборки первой строки можно выполнить действия со всем набором данных курсора: WHILE ©©FETCH STATUS = О BEGIN PRINT ©SchemaName + . + ©TableName + . + ©IndexName + is + CAST(©Fragmentation AS varchar) + % Fragmentented FETCH NEXT FROM TableCursor INTO ©SchemaName, ©TableName, ©IndexName, ©Fragmentat ion Напомним, что в книге уже приводилось краткое описание глобальной переменной @@FETCH STATUS. После выборки каждой строки значение @@FETCH STATUS обновляется, что позволяет определить, чем закончилась операция получения данных. Возможные значения @@FETCH STATUS приведены ниже. 0. Выборка выполнена успешно; ошибки не обнаружены. -1. Выборка окончилась неудачей; пропущена строка (конец курсора еще не достигнут, но со времени открытия курсора была удалена по крайней мере одна строка). Эта ситуация будет подробно рассматриваться в одном из следующих разделов. -2. Выборка окончилась неудачей; но на этот раз причиной является попытка чтения после последней строки в курсоре (или перед первой строкой). Такая ситуация также будет подробно описана ниже. После того как произойдет выход из цикла, действия с курсором, намеченные на данном этапе, будем считать выполненными, поэтому закроем курсор: CLOSE TableCursor Однако закрытие курсора не приводит к освобождению памяти, связанной с этим курсором. Фактически происходит только освобождение блокировок, относящихся к курсору. Чтобы обеспечить полный возврат в систему ресурсов, используемых курсором, необходимо отменить его распределение: DEALLOCATE TableCursor Ниже для удобства весь рассматриваемый код собран вместе. DECLARE ©SchemaName varchar(255) DECLARE ©TableName varchar(255) DECLARE ©IndexName varchar(255) DECLARE ©Fragmentation float DECLARE TableCursor CURSOR FOR SELECT SCHEMA NAME(CAST(OBJECTPROPERTYEX(i.object id, Schemald) AS int)), OBJECT NAME(i.obj ect id), i.name, ps.avg fragmentation in percent FROM sys.dm db index physical stats (DB ID(), NULL, NULL, NULL, NULL) AS ps JOIN sys.indexes AS i ON ps.object id = i.object id AND ps.index id = i.index id WHERE avg fragmentation in percent > 30 OPEN TableCursor FETCH NEXT FROM TableCursor INTO ©SchemaName, ©TableName, ©IndexName, ©Fragmentat ion WHILE ©@FETCH STATUS = 0 BEGIN PRINT ©SchemaName + . + ©TableName + . + ©IndexName + is + CAST(©Fragmentation AS varchar) + % Fragmentented FETCH NEXT FROM TableCursor INTO ©SchemaName, ©TableName, ©IndexName, ©Fragmentation CLOSE TableCursor DEALLOCATE TableCursor К этому моменту создан работоспособный фрагмент программного обеспечения, действующий на основе курсора, но фактически он не выполняет ничего нового по сравнению с тем, как если бы применялся отдельно взятый оператор SELECT (строго
|
© 2006 - 2024 pmbk.ru. Генерация страницы: 0.001
При копировании материалов приветствуются ссылки. |