|
Программирование >> Программирование баз данных
INTO CursorTable FROM Sales.SalesOrderHeader WHERE SalesOrderlD BETWEEN 43661 AND 43665 -- Создание уникального индекса в форме первичного ключа ALTER TABLE CursorTable ADD CONSTRAINT PKCursor PRIMARY KEY (SalesOrderlD) /* При выполнении оператора SELECT INTO бьшо автоматически сформировано значение ** IDENTITY, но решено использовать значение SalesOrderlD, сформированное в ** программе, поэтому необходимо ввести в действие параметр IDENTITY INSERT, ** чтобы можно было переопределить идентификационное значение */ SET IDENTITY INSERT CursorTable ON -- Объявление курсора DECLARE CursorTest CURSOR GLOBAL -- Параметр, позволяющий манипулировать курсором из -- кода, находящегося за пределами данного пакета SCROLL -- Параметр, позволяющий выполнять прокрутку назад и -- проверять результаты внесения изменений DYNAMIC -- Параметр, проверяемый на этот раз SCROLL LOCKS SELECT SalesOrderlD, CustomerlD FROM CursorTable -- Объявления двух вспомогательных переменных DECLARE ©SalesOrderlD int DECLARE ©CustomerlD varchar(5) -- Открытие курсора и получение первой строки OPEN CursorTest FETCH NEXT FROM CursorTest INTO ©SalesOrderlD, ©CustomerlD В приведенном выше блоке кода добавлена только одна строка. Остальные модификации сценария сводятся к удалению строк. Если читатель намеревается предпринять попытку применения этого сценария, то он должен внимательно проследить за всеми внесенными изменениями. В целом следует отметить, что проделанная автором корректировка сценария в основном сводится к тому, что исключен весь код, не относящийся к рассматриваемой теме, и основное внимание сосредоточено на изучении проблемы использования курсора. Но наиболее важное примечание к рассматриваемому сценарию состоит в том, что в нем были сознательно исключены даже те фрагменты кода, без которьпс при обычной эксплуатации сценария могут возникать нарушения в работе. Такие изменения кратко описаны ниже. При работе с курсором не применяется оператор CLOSE и даже не предусмотрено освобождение курсора. Не выполняется даже дальнейшая прокрутка после осуществления выборки первой строки. Причина, по которой курсор остается открытым, состоит в том, что мы должны создать ситуацию, в которой состояние эксплуатации приложения с открытым курсором сохраняется достаточно долго для того, чтобы мы могли провести эксперименты с блокировками. Кроме того, осуществляется выборка только первой строки, поскольку необходимо обеспечить, чтобы эта строка оставалась активизированной (в том виде, в каком сценарий примен5и1ся перед этим, нам приходилось проводить всю обработку вплоть до конца набора строк, прежде чем появл5и1ась возможность приступить к выполнению другого, возможно, конфликтующего оператора). Итак, мы должны сделать следующее: вызвать на выполнение приведенный выше сценарий, а затем открыть полностью отдельное окно соединения, притом что база данных AdventureWorks остается активизированной. После этого мы можем выполнить небольшую проверку в новом окне соединения: SELECT * FROM CursorTable Если читатель недостаточно внимательно следил за изложением материала в настоящем разделе, то приведенные ниже результаты могут стать для него неожраданными: SalesOrderlD CustomerlD 43661 442 43662 227 43663 510 43664 397 43665 146 (5 row(s) affected) Основываясь на тех сведениях о блокировках, которые были изложены в главе 12, можно предположить, что рассматриваемый оператор SELECT должен быть заблокирован в связи с наличием блокировок на текущей строке. Но при использовании блокировок прокрутки дело обстоит иначе. Блокировка распространяется только на ту строку, которая в настоящее время находится в курсоре, а что еще более важно, эта блокировка препятствует только обновлению данной строки. Любые операторы SELECT (подобные рассматриваемому в данном примере) позволяют просматривать содержимое курсора без каких-либо проблем. После этого, убедившись в том, что оператор SELECT применяется успешно, возвратитесь к исходному окну и выполните код, позволяющий продолжить нормальную эксплуатацию базы данных. Это тот же код, который примен5и1ся для той же цели в основной части настоящей главы: -- Удаление ненужных объектов CLOSE CursorTest DEALLOCATE CursorTest DROP TABLE CursorTable He забывайте вызывать на выполнение код, позволяющий освобождать ресурсы, подоб ный приведенному выше! Есяи вы не будете придерживаться этой рекомендации, то в системе появятся открытые транзакции, продолжающие действовать до закрытия соединения. Безусловно, в СУБД SQL Seruer предусмотрено освобождение всех ресурсов, распределенных для открытых транзакций, в случае разрыва соединения (путем выполнения отката), но автор сталкивался с такими ситуациями, что при выполнении программы проверки согласованности базы данных (DataBase Consistency Checker - DBCC) обнаруживается наличие транзакций, не закрытых в течение действительно очень долгого времени, в связи с тем, что в СУБД SQL Seruer не произошло автоматическое освобождение ресурсов. Опция OPTIMISTIC Применение оптимистических блокировок равносрыьно созданию такой ситуации, в которой для курсора вообще не устанавливаются блокировки прокрутки какого-либо типа. В основе организации работы с помощью оптимистических блокировок лежит предположение, что в процессе внесения изменений в данные, осуществляемом в одном пррыожении, не обнаружатся какие-то другие пррыожения, в которых потребуются те же данные. Такой подход к организации функционирования пррыожения рассматривается как оптимистический, поскольку в нем предполагается (точнее сказать, выражается надежда на то), что никому больше не потребуется вносить изменения в данные в интервале, протекающем с момента выборки данных в курсор и до момента внесения обновления в базу данных. Такой оптимизм не всегда является неоправданным. Если количество данных в базе данных весьма велико, а численность пользователей не столь значительна, то вероятность события, в котором два пользователя одновременно будут пытаться редактировать одну и ту же строку, становится крайне незначительной (разумеется, это зависит и от характера применяемьгх: бизнес-процессов). Тем не менее при использовании опции OPTIMISTIC нужно быть готовым к тому, что оптимистическое предположение окажется неверным, иными словами, кто-то попытается внести изменения в данные в тот период, когда после выполнения выборки происходит подготовка к фактическому обновлению данных в базе данных. При обнаружении подобной ситуации в СУБД SQL Server формируется сообщение об ошибке, а переменной @@ERROR присваивается значение 163 94. В таком случае необходимо осуществить полную повторную выборку данных из курсора (чтобы определить, какие произошли изменения), а затем либо выполнить откат транзакции, либо попытаться снова провести обновление. Обнаружение случаев преобразования типов курсора: TYPE WARNING Задача обнаружения случаев преобразования типов курсора является несложной. Достаточно ввести в объявление курсора опцию TYPE WARNING, после чего будут передаваться извещения обо всех неявных преобразованиях, которые выполнены по отношению к курсору. Если же в операторе объявления курсора эта опция не предусмотрена, то происходит только преобразование, а извещение не передается. Безусловно, осуществление такого преобразования, которое не было предусмотрено, вполне может привести к появлению одной из наиболее неприятных ситуаций, которые могут возникать в процессе эксплуатации программного обеспечения (к появлению непредсказуемых результатов). По-видимому, проще всего проиллюстрировать такую возможность на примере, поэтому вернемся к одной из изложенных выше тем и применим один из вариантов сценария создания курсора, который использовался в основной части данной главы. В данном примере особое внимание будет уделено тому фрагменту кода, в котором создается ключ для таблицы. Напомним, что попытка создания ключевого курсора на таблице, не имеющей уникального индекса, приводит к неявному преобразованию этого курсора в статический курсор: USE AdventureWorks /* Создается таблица, с которой будут проводиться эксперименты в этот раз */ SELECT OrderlD, CustomerlD
|
© 2006 - 2024 pmbk.ru. Генерация страницы: 0
При копировании материалов приветствуются ссылки. |