|
Программирование >> Программирование баз данных
в том, чтобы создаваемый курсор соответствовал своему назначению). Упрощению задачи выбора параметров способствует то, что многие параметры взаимосвязаны, поэтому, выбрав один параметр, вы получаете возможность быстро определить все прочие зависящие от него параметры. Приступим к практическим действиям и применим приведенный выше синтаксис для поэтапного решения задачи создания курсора, что позволяет последовательно рассматривать важные понятия, относящиеся к разным этапам формирования объявления. Область определения Область определения курсора зависит от выбора параметра LOCAL или GLOBAL; под этим подразумевается, что от применяемого параметра зависит, в каких соединениях и процессах может быть получен доступ к курсору. Вообще говоря, при задании области определения для большинства программных объектов по умолчанию следует принимать наиболее консервативный подход, иначе говоря, сводить область определения к минимуму (выполнение этой рекомендации в данном случае соответствует применению параметра LOCAL). Но курсоры SQL Server представляют собой своего рода исключение из этого правила, поскольку по умолчанию они имеют область определения GLOBAL. Прежде чем перейти к описанию последствий, связанных с применением параметра LOCAL или GLOBAL, необходимо пояснить, что подразумевается под понятиями локальный (LOCAL) и глобальный (GLOBAL) в этом контексте. Как уже было сказано, мы уже сталкиваемся с исключением, когда обнаруживаем, что по умолчанию курсоры SQL Server имеют так называемую глобальную область определения, а не локальную, более ограничительную. Но на этом исключения не заканчиваются. Если в СУБД SQL Server какой-то объект обозначается как глобальный, а не локальный, это обычно означает, что доступ к этому объекту предоставляется во всех соединениях, а не только в текущем соединении. Но если речь идет об объявлении курсора, чему посвящен данный раздел, то под понятием глобальности подразумевается то, могут ли полушть доступ к курсору в текущем соединении все процессы (пакеты, триггеры, хранимые процедуры), а не только текущий процесс. Схема, позволяющая пояснить рассматриваемую тему, приведена на рис. 15. L Глобальный I = В области определения I = Вне области определения Все пространство памяти SQL Server Текущее соединение Текущий процесс Локальный I = В области определения I = Вне области определения Все пространство памяти SQLServer Текущее соединение Текущий процесс Рис. 15.1. Схема, поясняющая различия между понятиями локального и глобального курсоров Кратко коснемся того, какие выводы из этого следуют, и выполним небольшую проверку. Как и можно было предположить, применение по умолчанию глобального доступа имеет свои преимущества и недостатки. Наличие глобальной области определения означает, что курсор можно создать с помощью одной хранимой процедуры и обратиться к нему из другой хранимой процедуры; при этом не обязательно даже передавать ссылку на этот курсор. В этом состоит значительное преимущество такой организации работы. Но обнаруживается также один недостаток, связанный с тем, что при попытке создать другой курсор с тем же именем возникает ошибка. Проверим, обосновано ли это утверждение, на небольшом примере. Для этого подготовим хранимую процедуру, которая будет создавать курсор от нашего имени: USE AdventureWorks GO CREATE PROCEDURE spCursorScope AS DECLARE ©Counter int, ©OrderlD int, ©CustomerlD int DECLARE CursorTest CURSOR GLOBAL SELECT SalesOrderlD, CustomerlD FROM Sales.SalesOrderHeader SELECT ©Counter = 1 OPEN CursorTest FETCH NEXT FROM CursorTest INTO ©OrderlD, ©CustomerlD PRINT Row + CAST(©Counter AS varchar) + has a SalesOrderlD of + CONVERT (varchar, ©OrderlD) + and a CustomerlD of + CAST (©CustomerlD AS varchar) WHILE (@Counter<=5) AND (@©FETCH STATUS=0) BEGIN SELECT ©Counter = ©Counter + 1 FETCH NEXT FROM CursorTest INTO ©OrderlD, ©CustomerlD PRINT Row + CAST(©Counter AS varchar) + has a SalesOrderlD of + CONVERT (varchar, ©OrderlD) + and a CustomerlD of + CAST (©CustomerlD AS varchar) В этой хранимой процедуре заслуживают внимания несколько особенностей. Прежде всего, было объявлено несколько вспомогательных переменных, предназначенных для хранения важной для нас информации. Первая из этих переменньгх, ©Counter, применяется для контроля над ситуацией, чтобы мы имели возможность продвигаться в курсоре всего на несколько строк, а не проходить сразу весь набор записей. Вторая и третья переменные, ©OrderlD и ©CustomerlD, применяются для хранения значений, полученных при выполнении запроса, в ходе того, как осуществляется построчное перемещение через результирующий набор. После этого приведено само объявление курсора. Обратите внимание на то, что в этом примере область определения указана явно. Если бы ключевое слово GLOBAL было исключено, то по умолчанию был бы по-прежнему получен курсор, имеющий глобальную область определения. Но мы не обязаны придерживаться этого значения предусмотренного по умол чанию Чтобы присвоить опции * применения по умолчанию локального курсора значение True можно воспользоваться процедурой sp dboption или операто ром ALTER DATABASE (чтобы снова перейти к применению по умолчанию гло бального курсора достаточно присвоить этой опции значение False) Как оказалось, рассматриваемый пример стал еще одной великолепной иллюст рацией к рекомендации, касающейся того, что следует всегда явно указывать значения всех применяемых параметров, а не рассчитывать на то что по умолча нию эти параметры будут иметь нужные вам значения Представьте себе, что вы рассчитываете на наличие заданного по умолчанию значения GLOBAL и не знаете о том, что кто то внес изменение в эту опцию в масштабах всей системы По подоб ному поводу автору часто приходится слышать возражения что вряд ли на пред приятии найдутся те кто будет вносить столь существенные изменения Но это - неправильное мнение Подобные корректировки относятся к категории тех * мелких поправок которые вносят разработчики или администраторы чтобы устранить какое то нарушение в работе в другом месте В зависимости от того насколько тщательно ведется контроль над использованием курсоров мо гут пройти недели прежде чем будет обнаружено что вместо глобального кур сора применяется локальный или наоборо!, а к тому времени все напрочь забу дут о том что когда то было изменено значение применяемое по умолшнию Вернемся к рассматриваемому примеру, откроем курсор и обработаем несколько строк. Но важно отметить, что курсор не был закрыт или освобожден, поскольку при выходе из хранимой процедуры курсор был оставлен открытым и доступным. Но автор специально предусмотрен такой вариант развития событий, чтобы подчеркнуть, что подобное применение курсора является недопустимым. При этом возникает значительная опасность. Оставляя курсоры открытыми, как в данном примере, вы невольно создаете предпосылки возникновения всевозможных нарушений в работе. Сам автор в данном случае поступил таким образом, чтобы продемонстрировать понятие области определения, но следует еще раз порекомендовать, чтобы при подобной организации работы соблюдались исключительные меры предосторожности. В частности, опасность заключается в том, что при вызове данной хранимой процедуры не будет учитываться отсутствие в ней собственных средств освобождения ресурсов. Поэтому, если за пределами этой хранимой процедуры не будет предусмотрено применение средств возврата ресурсов, распределенных для курсора (закрытия и освобождения), станет происходить своего рода утечка ресурсов из-за наличия такого оставленного без присмотра но все еще активного курсора. Кроме того, возникают предпосылки появления ошибок при повторном вызове той же хранимой процедуры (поскольку фактически при этом будет предприниматься попытка снова объявить и открыть тот же курсор, притом что он уже существует). Рассматривая варианты объявления курсора для вывода, можно обнаружить гораздо более явные и лучшие возможности для использования курсора в тех ситуациях, когда необходимо обеспечить взаимодействие с курсором извне.
|
© 2006 - 2024 pmbk.ru. Генерация страницы: 0
При копировании материалов приветствуются ссылки. |