Программирование >>  Программирование баз данных 

1 ... 177 178 179 [ 180 ] 181 182 183 ... 346


Все ключи сохраняются в одной из собственных таблиц базы данных 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. После этого появляется второй результирующий набор. Именно с этого момента обнаруживаются более интересные особенности.



1 ... 177 178 179 [ 180 ] 181 182 183 ... 346

© 2006 - 2024 pmbk.ru. Генерация страницы: 0.001
При копировании материалов приветствуются ссылки.
Яндекс.Метрика