|
Программирование >> Программирование баз данных
Все ключи сохраняются в одной из собственных таблиц базы данных tempdb. В СУБД SQL Server такой набор ключей используется для поиска данных после передачи с помощью курсора запроса на получение определенной строки, охватываемой курсором. В данный момент необходимо подчеркнуть важную особенность, что во время выполнения оператора FETCH происходит выборка фактических данных на основе значения ключа. Из этого вытекает важное следствие, что данные любой конкретной строки при выборке этой строки с помощью курсора всегда находятся в актуальном состоянии. Недостатком (или достоинством) такого подхода, в зависимости от того, для чего применяется курсор, является сам факт заблаговременного создания набора ключей до выполнения операции поиска. Из того, что набор ключей создается заранее, следует, что этот набор ключей уже охватывает все строки, которые должны быть включены в курсор. Иначе говоря, все строки, добавленные в основополагающую таблицу после создания курсора, остаются недоступными для курсора, даже если они соответствуют условию конструкции WHERE в операторе SELECT курсора. А строки, которые уже входят в состав курсора, могут быть обновлены в операциях с курсором, в зависимости от того, какие опции курсора были выбраны при его создании. Внесем изменения в рассматривавшийся ранее сценарий, чтобы проиллюстрировать затронутую проблему чувствительности к изменениям данных при использовании ключевого курсора: USE AdventureWorks /* Создается таблица, с которой будут проводиться эксперименты в этот раз */ SELECT SalesOrderlD, CustomerlD 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 -- Параметр, позволяющий выполнять прокрутку назад и -- проверять результаты внесения изменений KEYSET -- Параметр, проверяемый на этот раз SELECT SalesOrderlD, CustomerlD FROM CursorTable -- Объявления двух вспомогательных переменных DECLARE ©SalesOrderlD int DECLARE ©CustomerlD varchar(5) -- Открытие курсора и получение первой строки OPEN CursorTest FETCH NEXT FROM CursorTest INTO ©SalesOrderlD, ©CustomerlD -- Обработка данных в цикле WHILE ®®FETCH STATUS = О BEGIN PRINT CAST(©SalesOrderlD AS varchar) + + ©CustomerlD FETCH NEXT FROM CursorTest INTO ©SalesOrderlD, ©CustomerlD -- Внесение изменения. Будет показано, что на этот раз изменение повлияет на -- работу курсора UPDATE CursorTable SET CustomerlD = -111 WHERE SalesOrderlD = 43663 -- Удаление строки для ознакомления с тем, как осуществляется эта операция DELETE CursorTable WHERE SalesOrderlD = 43664 -- Вставка строки. Далее будет показано, что эта строка не обнаруживается -- в курсоре INSERT INTO CursorTable (SalesOrderlD, CustomerlD) VALUES (-99999, -99999) -- Проверка таблицы для определения того, что в ней действительно отражены -- внесенные изменения SELECT SalesOrderlD, CustomerlD FROM CursorTable -- Переход в начало набора данных. Это возможно, поскольку курсор является -- прокручиваемым FETCH FIRST FROM CursorTest INTO ©SalesOrderlD, ©CustomerlD /* Повторная обработка в цикле. На этот раз следует учитывать, что проверяемые ** данные изменились. Не исключена возможность того, что некоторые строки ** отсутствуют (удалены), поэтому не будут обнаружены при обработке данных ** в курсоре; таким образом, должна быть предусмотрена немного более сложная ** проверка состояния курсора */ WHILE ©©FETCH STATUS != -1 BEGIN IF ©©FETCH STATUS = -2 BEGIN PRINT MISSING 1 It probably was deleted. ELSE BEGIN PRINT CAST (©SalesOrderlD AS varchar) + + CAST (©CustomerlD AS varchar) FETCH NEXT FROM CursorTest INTO ©SalesOrderlD, ©CustomerlD -- Удаление ненужных объектов CLOSE CursorTest DEALLOCATE CursorTest DROP TABLE CursorTable В caMPix внесенных нами модификациях нет ничего особенного. Просто бьыи учтены условия создания ключевого курсора и в связи с этим добавлен требуемый уникальный индекс. В данном случае оказалось, что в наибольшей степени подходит первичный ключ, поскольку он позволяет проще всего осуществлять выборку требуемых данных из конкретной таблицы, но для этой цели может применяться также любой другой уникальный индекс, не относящийся к первичному ключу. Кроме того, в сценарий введен дополнительный код, позволяющий вставлять в таблицу строки с данными, чтобы мы могли наглядно убедиться в том, что ключевой курсор, созданный на основе этого набора ключей, не позволяет найти вновь вставленную строку. Но, по-врщимому, наиболее важной особенностью новой версии сценария является то, что изменено условие цикла WHILE, применяемого в заключительном прогоне через курсор. С формальной точки зрения это изменение следовало внести в оба цикла, но в текущих этапах эксплуатации рассматриваемого сценария риск столкнуться с удаленными строками равен нулю, а автор стремился к тому, чтобы искомое различие можно было обнаружить непосредственно при выполнении одного и того же сценария. Таким образом, модификации, внесенные в сценарий, касались обнаружения только тех новых особенностей, о которых вдет речь, - ввода строки лишь для обнаружения того, что она теперь отсутствует. Наиболее правдоподобная гипотеза, которая приходит на ум при обнаружении такой ситуации, состоит в том, что кто-то удалил эту строку. Поэтому ознакомимся с результатами, полученными после выполнения модифицированного сценария: (5 row(s) affected) 43661 442 43662 227 43663 510 43664 397 43665 146 (1 row(s) affected) (1 row(s) affected) (1 row(s) affected) SalesOrderlD CustomerlD -99999 -99999 43661 442 43662 227 43663 -111 43665 146 (5 row(s) affected) 43661 442 43662 227 43663 -111 MISSING! It probably was deleted. 43665 146 Ниже приведено краткое описание основных обнаруживаемых при этом особенностей. Сценарий начинает свою работу в основном так же, как и в предыдущей версии. Обнаруживаются те же пять строк в первом результирующем наборе, что и в последний раз. Затем обнаруживается дополнительный ряд сообщений со словом affected , касающихся затронутых строк; эти сообщения относятся к дополнительно введенным в этой версии операторам INSERT, UPDATE и DELETE. После этого появляется второй результирующий набор. Именно с этого момента обнаруживаются более интересные особенности.
|
© 2006 - 2024 pmbk.ru. Генерация страницы: 0.001
При копировании материалов приветствуются ссылки. |