МЕЖДУНАРОДНЫЙ БАНКОВСКИЙ ИНСТИТУТ INTERNATIONAL BANKING INSTITUTE ТЕМА 8. ПРАКТИЧЕСКОЕ ЗАНЯТИЕ 1. ВСТРОЕННЫЙ SQL. ПОНЯТИЕ КУРСОРА. Цель: изучить изменения в синтаксисе SQL-запросов, вызванные необходимостью встраивать команды SQL в базовый язык программирования. Для достижения поставленной цели необходимо решить следующие задачи: Изучить принципы изменения синтаксиса SQL-запросов при их встраивании в программы на базовом языке программирования Изучить синтаксис и базовые операторы языка Transact SQL, используемые при работе с серверными курсорами. Научиться применять операторы работы с курсорами для организации построчной обработки SQL-запросов. Оглавление. Основные языковые конструкции Transact SQL ....................................................................2 Выражения в TRANSACT SQL ................................................................................................3 Управляющие операторы........................................................................................................11 Задание 1...................................................................................................................................21 Задание 2...................................................................................................................................21 Результатом работы SQL-запросов является набор данных. Этот набор данных передается целиком клиенту, подавшему запрос, и дальше обрабатывается им. Иногда требуется работа не со всем набором данных, а с одной строкой или с некоторой частью результирующего набора. Кроме того, передача неограниченного или большого набора данных на клиент вызывает непроизводительную загрузку сети, поэтому возникает необходимость непосредственно на сервере работать с отельными строками. Для обеспечения такого механизма вводятся новые объекты обработки данных, называемые курсорами. Курсоры бывают серверные и клиентские. Клиентские курсоры, получив от сервера результат в виде набора данных, предоставляют возможность навигации по нему, выбирая по одной строке и работе с ней. Клиентские курсоры реализуются не на сервере, а на клиенте. Мы будем говорить про серверные курсоры и в дальнейшем говоря “курсор” будем иметь ввиду именно их. Серверный курсор – это механизм, позволяющий работать с отдельными строками на уровне сервера. Обычно это происходит до выдачи результата клиенту. Для работы с курсором добавляется несколько новых операторов SQL. Операторы по работе с курсором встраиваются в базовый язык программирования конкретного сервера МЕЖДУНАРОДНЫЙ БАНКОВСКИЙ ИНСТИТУТ INTERNATIONAL BANKING INSTITUTE баз данных. На сервере MS SQL Server используется в качестве базового языка язык Transact SQL. Основные языковые конструкции Transact SQL Transact SQL это базовый язык MS SQL Sever, который позволяет писать процедуры и функции с использованием операторов встроенного SQL. Все объекты MS SQL Server 2000 имеют собственные имена, на которые можно ссылаться в программах – эти имена называются идентификаторами, в Transact SQL имеются следующие ограничения на идентификаторы: первый символ должен соответствовать стандарту UNICODE standart 2.0 – один из символов латинского или национального алфавита либо символом подчеркивания(т.е. нельзя называть ! № ; и т.д.). имена временных таблиц начинаются с символов # или ##; имена внутренних переменных начинаются с символа @ для обозначения глобальных переменных локальных переменных и с двойного символа @@ для обозначения глобальных переменных; нельзя использовать зарезервированные слова в качестве идентификаторов; в именах объектов на MS SQL Server не различается регистр; запрещается использовать внутри идентификаторов пробелы и спец символы !, %, ^, &, -, {, }, ‘ , \, ` ; длина имени объектов не должна превышать 128 символов, а для временных таблиц 116 символов; для обхода некоторых ограничений можно заключать имена в двойные кавычки или в квадратные скобки. В этом случае в качестве имен могут быть использованы ключевые слова и в идентификаторах могут быть пробелы. Такие идентификаторы называются «Ограниченными идентификаторами» (Delimited identifiers). Однако желательно не использовать их в Ваших процедурах и функциях. Каждый объект в MSSQL Server 2000 создается определенным пользователем и принадлежит какой-либо базе данных, поэтому вводится понятие полного квалифицированного (определенного) имени объекта (full qualified name). Это имя включает последовательно, отделенные друг от друга точкой, имена сервера, базы данных, владельца базы данных и самого объекта. [[server.] [database ].[owner_name].] object_name Разрешается пропускать отдельные части, но точки, которые остаются внутри полного имени, должны оставаться. Например: МЕЖДУНАРОДНЫЙ БАНКОВСКИЙ ИНСТИТУТ INTERNATIONAL BANKING INSTITUTE Server…object_name Owner_name.object_name Database..object_name Выражения в TRANSACT SQL Выражения в языке TransacTransact SQL это комбинация функций, логических и арифметических операций, констант и других объектов. Выражения состоят из операндов и операторов. Операндами выражений могут быть: константы например:. 2.45 ‘просто текст’; функции; имена колонок; переменные; подзапросы; конструкция типа CASE, NULLIF, COALESCE. Все эти конструкции позволяют использовать логическое условие, для определения возвращаемого результата. SQL Server допускает следующие простые операторы (см. табл.1). Таблица 1. Примеры простых операторов в Transact SQL Название Обозначение, пример Сложение + Set @n=@n+1 Вычитание Set @m=@n-2 Умножение * Деление / Остаток от деления % Побитное И & Побитное ИЛИ | Побитное НЕ ~ Исключающее ИЛИ ^ Равно = Больше > Меньше < Больше или равно >= Меньше или равно <= Неравно <> или != (нестандартно!) Не больше !> МЕЖДУНАРОДНЫЙ БАНКОВСКИЙ ИНСТИТУТ INTERNATIONAL BANKING INSTITUTE Не меньше LEFT OUTER JOIN RIGHT OUTER JOIN Конкатенация строк !< *= левое внешнее объединение =* правое внешнее объединение + ‘фамилия’+’ имя ’ Описание переменных В Transact SQL существует несколько способов хранения и передачи данных. Одним из таких способов является хранение и передача данных с использованием переменных. В языке Transact SQL смысл переменной аналогичен смыслу в других языках, т.е. переменная – это именованная область памяти, значение которой может изменяться. То, как сервер будет интерпретировать последовательность бай памяти, на которые ссылается переменная, зависит от типа данных, ассоциированных с переменной. Перед использованием переменной она должна быть объявлена, для этого существует оператор объявления переменной DECLARE @<идентификатор переменной> <тип данных> Единичный знак @ - является признаком локальной переменной. Локальная переменная видна только в том модуле, где она определена, при выходе из этого модуля локальная переменная не видна. Для описания глобальный переменных используется двойной знак @@, предваряющий имя переменной. Однако следует сказать, что глобальные переменные активно использует сам сервер, поэтому существует опасность войти с ним в противоречие. В одной операторе DECLARE могут быть описаны несколько переменных, каждое описание отделяется от следующего запятой. Например: Declare @n int, @name_s varchar(10) - мы описали две переменных, одна из них @n имеет целочисленный типа данных, а вторая @name_s имеет символьный тип данных с переменной длиной в пределах 10 символов. Типы данных определяют представление колонок таблиц, параметров процедур и переменных. В SQL Server помимо предопределенных системных типов данных можно создавать и пользовательские типы, основывающиеся на системных. В SQL Server все типы данных регистонезависимые, в силу чего недопустимо использование различных пользовательских типов данных, отличающихся только регистром. Допустимы следующие системные типы данных (см. табл. 2). Таблица 2. МЕЖДУНАРОДНЫЙ БАНКОВСКИЙ ИНСТИТУТ INTERNATIONAL BANKING INSTITUTE Системные типы данных Вид данных Двоичные Символьные Дата и время Точное представление чисел Представление чисел с плавающей точкой Целочисленные типы Денежные типы Специальные Текст и картинки Синонимы Денежные типы Специальные Текст и картинки Системное представление binary[(n)] varbinary[(n)] char[(n)] varchar[(n)] Datetime smalldatetime decimal[(p[, s])] numeric[(p[, s])] float[(n)] real int - 4 байта smallint - 2 байта tinyint -1 байт Money smallmoney Bit timestamp типы, определяемые пользователем Text image binary varying для varbinary character для char character для char (1) character (n) для char (n) character varying (n) для varchar (n) dec для decimal integer для int double precision для float float [(n)] для n = 1√7 для real float [(n)] для n = 8√15 для float Money smallmoney Bit timestamp типы, определяемые пользователем Text МЕЖДУНАРОДНЫЙ БАНКОВСКИЙ ИНСТИТУТ INTERNATIONAL BANKING INSTITUTE image Оператор присваивания значений переменных Присваивать значения переменным следует с помощью инструкции SET. Ее синтаксиc: SET <имя_переменной>=выражение Здесь выражение должно иметь тот же тип, что и переменная или же должно допускаться неявное преобразование типов между типом результата выражения и типом переменной. Пример1: DECLARE @a INT, @b VARCHAR(20) SET @A=3 SET @B=’Тестовая строка’ Можно также записывать значения в переменные с помощью оператора SELECT. Для этого в разделе SELECT перечисляются переменные и выражения: SELECT <имя_переменной>=выражение [, …n] <дальнейшее описание оператора SELECT> <дальнейшее описание оператора SELECT> - запрос на языке SQL Пример2: DECLARE @N INT, @b VARCHAR (20) Set @b=’Иванов И.А.’ SELECT @N=N_Reader FROM Readers Where Name_Reader= @b В переменную @N будет занесен номер читательского билета читателя Иванова И.А. Рекомендуется использовать SELECT для присвоения переменных только в том случае, если в выражении имеются столбцы таблиц или представлений, имеющихся в БД, как, например, в приведенном выше примере. Если выражение включает только константы, переменные и функции, то следует пользоваться оператором SET. Также стоит обратить внимание на то, что при использовании оператора SELECTнельзя комбинировать вывод результатов и присвоение переменных. Если оператор SELECT возвращает несколько строк, то, при использовании для записи значений переменных оператора SELECT, в переменные будут записаны значения соответствующих столбцов первой строки результирующего набора данных, остальные строки будут потеряны. Оператор SELECT, который в списке вывода содержит только список имен столбцов таблиц БД или список переменных МЕЖДУНАРОДНЫЙ БАНКОВСКИЙ ИНСТИТУТ INTERNATIONAL BANKING INSTITUTE предназначен для вывода результатов. Поэтому если мы хотим вывести результат выполнения предыдущей команды присвоения значений переменной @N на экран мы можем написать оператор Select @N Для того, чтобы вывести результаты выполнения арифметических операторов также используется SELECT Например: SELECT 7%4, 4*7, ((45+18)/5.0) - 4, ((45+18)/5) - 4 --------- ---------- ---------------------- --------------------3 28 8.6000000 4 Арифметические операторы возвращают результат того же типа, что и тип операндов. В результате выполнения операций сравнения возвращается логическое значение, но если сравнение невозможно возвращается NULL – неопределенное значение. Операция сравнения невыполнима – тогда, когда, либо сравниваются операнды разных типов, или когда один из сравниваемых операндов имеет неопределенное значение. Комментарии – являются одними из важнейших элементов языка. Комментарии позволяют использовать принцип самодокументирования программного кода, а это облегчает сопровождение и модификацию программ. В Transact SQL комментарии бывают 2-х типов – однострочные и они оформляются двумя последовательными дэфисами в строке. --Текст комментария Многострочный комментарий заключается в символы слэшзвездочка - звездочка слэш , например /* Текст комментария строка 1 Комментарий строка 2 */ При написании кода на Transact SQL широко используются встроенные функции. В общем случае этих функций много, но они подразделяются на несколько разделов. Таблица 3. Функции по работе с датами (Date Functions) Date function DATEADD DATEDIFF Format (datepart, number, date) (интервал,число, дата) (datepart, date1, date2) Описание Добавляет дату Возвращает разницу между указанными частями дат dat1 МЕЖДУНАРОДНЫЙ БАНКОВСКИЙ ИНСТИТУТ INTERNATIONAL BANKING INSTITUTE DATENAME (datepart, date) DATEPART (datepart, date) GETDATE() Day() Month() Year() ISDATE(ex) (date) (date) (date) Полное Year Quarter Month Dayofyeaar Day Week Hour Minute Second Millisecond и dat2 в заданном интервале Возвращает строковое представление заданной части даты Возвращает целочиленной представление заданной части даты Возвращает текущую дату Возвращает число Возвращает месяц (число) Возвращает число год 1 если символьная строка м.б. переведена в datetime или smalldatetime Таблица 4. Допустимые значения параметра интервал: Сокращенное Перевод Yy или yyyy Год Qq или q Квартал Mm или m Месяц Dy или y День года Dd или d День Wk ww Неделя Hh Час Mi Минута Ss или s Секунда Ms Миллисекунда Таблица 5. Математические функции (применимы только к числовым данным): ABS ACOS ASIN ATAN ATN2 Абсолютная величина Арккосинус Арксинус Арктангенс Atan2(fload Возвращает угол в радианах, тангес _expr,fload_ которого равен частному от деления ex) первого аргумента на второй с учетом квадрата,задаваемого двумя МЕЖДУНАРОДНЫЙ БАНКОВСКИЙ ИНСТИТУТ INTERNATIONAL BANKING INSTITUTE аргументами CEILING Ближайшее целое большее или равное аргументу (округление вверх) COS Косинус угла COT Котангенс угла DEGREES Преобразование угла из радиан в градусы EXP Экспонента FLOOR(ex) Возвращает ближайшее минимальное целое (округление с отбрасыванием) SIGN Если положительное то 1, нулевое 0 Отрицательное –1 ISNUMERIC( Проверяет тип выражения, если ex) числовой возвращает 1, в противном случае LOG Логарифм по основанию LOG10 Логарифм десятичный PI Число Пи POWER Power(x,y) X в степени y RADIANS Переводит углы в радианы RAND Rand([seed] Генерирует случайное число в ) диапазоне от 0 до 1, аргумент задает начальное значение (начальную установку генератора) Если аргумент не используется, то начальное значение генерируется на основе системного времени ROUND Округление числа с заданной точностью в кол-ве знаков после запятой SIN Синус SQRT Квадратный корень TAN Тангенс Таблица 6. Len LTRIM RTRIM LEFT RIGHT LOWER Символьные функции Возвращает длину строки Удаляет пробелы в начале строки Удаляет пробелы в конце строки Возвращает левую часть строки Возвращает правую часть строки В верхний регистр МЕЖДУНАРОДНЫЙ БАНКОВСКИЙ ИНСТИТУТ INTERNATIONAL BANKING INSTITUTE UPPER STR SUBSTRING CHARINDEX PATINDEX SPASE REPLICATE STUFF Revers QUOTENAME Нижний регистр Преобразует число в строку Выделяет подстроку Выполняет поиск подстроки Выполняет поиск подстроки по шаблону @a=Spase Возвращает указанное число пробелов (10) Заменяет все подстроки строки на указанное значение Select Удаляет символы указанного фрагмента, stuff(‘setre и заменяет их на другую подстроку d’,3,5,’use’ ) ----Seused Переворачивает строку задом наперед Конвертирует строку в UNICODE Наиболее часто используемыми являются функции преобразования. К ним относятся функция сast и функция Convert. CAST(expression as data_type) – используется для преобразования из одного типа данных в другой тип данных. Функция CONVERT используется для преобразования в тип данных datetime, smalldatetime даных типа nchar,nvarchar,char,varchar CONVERT (datatype[(length)], expression [, style]) Значение параметра стиль приведен в табл.7 Таблица 7. Коды стилей при преобразовании даты. Без века С веком Стандарт Формат отображения (УУ) (УУУУ) 0 или 100 по умолчанию mon dd yyyy hh:miAM (или PM) 1 101 USA mm/dd/yy 2 102 ANSI yy.mm.dd 3 103 English/French Dd/mm/yy 4 104 German dd.mm.yy 5 105 Italian dd-mm-yy 6 106 Dd mon yy 7 107 Mon dd,yy МЕЖДУНАРОДНЫЙ БАНКОВСКИЙ ИНСТИТУТ INTERNATIONAL BANKING INSTITUTE 8 9 108 109 10 11 12 13 110 111 112 113 USA Japan ISO Europa Hh:mi:ss mon dd yyyy hh:mi:sssAM (илиPM) mm-dd-yy Yy/mm/dd Yymmdd dd mon yyyy hh:mi:ss:mmm(24часа) Например, для того, чтобы преобразовать переменную VarChar(10) в тип данных Smalldatetime при использовании европейского типа представления текущей даты надо использовать следующий формат: Convert(varchar(10),@dd,104) В табл. 8 приведены наиболее часто используемые системные функции. Таблица 8. Системные функции. Функция Параметр(ы) Возвращаемая информация COALES (выражение1, Возвращает первое выражение, CE выражение2,…, которое не равно NULL выражениеN) ISNULL (выражение, Возвращает значение, если встретит значение) NULL (заменяет Null на значение) NULLIF (выражение1, Возвращает NULL, когда выражение 1 выражение2) равно NULL, а также когда выражение 1 и выражение 2 эквивалентны SQL server контролирует ход работы всех пользователей. Сервер передает с помощью глобальных переменных ряд значений, которые приложения могут у себя использовать для корректировки хода выполнения программы. Можно выделить следующие глобальные переменные конфигурирования @@DBTS – текущее значение счетчика timestamp @@ROWCOUNT – возвращает количество строк которые были обработаны последней командой SELECT @@ERROR - возвращает код последней ошибки в текущем соединении Управляющие операторы Begin … End операторные скобки Ключевые слова BEGIN и END применяются для обозначения набора МЕЖДУНАРОДНЫЙ БАНКОВСКИЙ ИНСТИТУТ INTERNATIONAL BANKING INSTITUTE инструкций Transact SQL, который должен быть выполнен как один блок. Синтаксис: BEGIN инструкции END Условная конструкция IF... ELSE Ключевые слова IF и ELSE предназначены для контроля условного выполнения инструкций внутри хранимой процедуры. Они дают возможность проверять наличие определенного состояния и выполнять инструкцию, являющуюся частью ветви IF, или инструкцию, являющуюся частью ветви ELSE. Критерий проверки определяется выражением, следующим за ключевым словом IF. Синтаксис инструкции IF ... ELSE: IF логическое выражение { инструкция | блок инструкций } [ ELSE { инструкция | блок инcтрукций } ] В следующем примере инструкция PRINT применяется для вывода сообщения, подтверждающего наличие в таблице базы данных строки, соответствующей заранее заданным условиям. Если такой строки не существует, выдается сообщение "Сведений нет". Так как ветвь ELSE в данном примере не применяется, сообщение "Сведений нет" выводится также и после сообщения о результатах проверки. IF EXISTS ( SELECT * FROM Readers WHERE Name_reader= 'Иванов И.А.’) PRINT 'Сведения о таком читателе в Базе данных есть' ELSE PRINT 'Сведений нет' Оператор выбора Синтаксис: CASE expression WHEN expression1 THEN exression1 [[WHEN expression2 THEN expression2[..]] [ELSE expressionN] END CASE <вводимое выражение> WHEN { <сравниваемое выражение> | < условное выражение> } THEN <конечное выражение> WHEN {<сравниваемое выражение> | < условное выражение> } THEN <конечное выражение> МЕЖДУНАРОДНЫЙ БАНКОВСКИЙ ИНСТИТУТ INTERNATIONAL BANKING INSTITUTE … [ELSE <конечное выражение>….] END Пример: DECLARE @v char(8) Set @v = (select dol from prof where name = ‘Сидоров’) Print CASE @v When ‘acп’ THEN ‘аспирант’ When ‘ac’ THEN ‘ассистент’ When ‘доц’ Tnen ‘доцент’ When ‘проф’ THEN ‘профессор’ When ‘cт’ THEN ‘стажер’ When ‘cтуд’ THEN ‘студент’ ELSE ‘непонятно’ END Можно использовать прямо в запросе Select Category = Case type When ‘уч. пос’ THEN ‘учебное пособие’ When ‘мет.к л.р.’ THEN ‘методические указания к лабораторным работам’ When ‘мет к кур.’ THEN ‘методические указания к курсовому проекту’ END, Title AS ‘Полное название’, AUTOR AS ‘Автор’ FROM BOOKS Where YEAR_IZD > 1980 Циклы. Конструкция WHILE Цикл WHILE применяется для выполнения одной или нескольких инструкций TRANSACT SQL, при истинности заданного условия. Инструкция, следующая за WHILE, выполняется циклически, пока проверяемое условие истинно. Синтаксис инструкции WHILE: WHILE логическое_выражение <инструкция_SQL_1> [BREAK] <инструкцця SQL_2> [CONTINUE] Если в цикл необходимо включить несколько инструкций, используйте описанную выше конструкцию BEGIN ... END. МЕЖДУНАРОДНЫЙ БАНКОВСКИЙ ИНСТИТУТ INTERNATIONAL BANKING INSTITUTE BREAK - применяется внутри блока команд TRANSACT SQL, находящихся внутри условной инструкции WHILE. Результатом выполнения предложения BREAK будет переход к первому оператору, следующему за концом блока цикла WHILE. CONTINUE – ключевое слово, после выполнения которого все инструкции, следующие от него до инструкции, завершающий блок цикла WHILE будут пропущены и управление будет передано на начало цикла (первую инструкцию в блоке цикла). DECLARE @I INT, @C INT, @N SELECT @I = 1 SELECT @N =1 WHILE I=1 BEGIN /* начало внешнего блока */ SELECT @C= SELECT R1.COUNT_T From R1 Where R1.Nun = @N IF @C <> 0 Then Begin /* начало внутреннего блока */ Select @N= @N+1 CONTINUE End /* конец внутреннего блока */ ELSE BREAK END /* конец внешнего блока */ WHILE <условие> { < выполняемый оператор > | <блок операторов>} [BREAK] – прервать цикл [CONTINUE] – продолжить цикл Оператор безусловного перехода GOTO Допускается вставлять операторы безусловного перехода, хотя и считается, что их использование является признаком плохого тона программирования. Синтаксис: GOTO метка Метка – указывает, куда должно быть передано управление, метка – идентификатор, который предшествует некоторому оператору и отделяется от него двоеточием. Пример: DECLARE @A INT SET @A=1 МЕЖДУНАРОДНЫЙ БАНКОВСКИЙ ИНСТИТУТ INTERNATIONAL BANKING INSTITUTE GOTO jump SET @A=2 Jump: SELECT @A Оператор WAITFOR С помощью этого оператора можно приостановить выполнение программы на некоторое время. Можно задать ожидание до некоего определенного времени (по системному таймеру), или на некоторый временной промежуток. Синтаксис оператора: WAITFOR { DELAY 'время_продолжения_рботы' } 'время_задержки' | TIME DELAY 'время_задержки' – указывает, что надо ждать указанное количество времени. Максимум можно указать 24 часа. TIME 'время_продолжения_рботы' – указывает, что нужно приостановить работу и продолжить ее только тогда, когда по систеному таймеру будет время, указанное как время_продолжения_рботы. Пример: PRINT 'Начало работы; Сейчас '+CONVERT (VARCHAR(20),GETDATE()) WAITFOR DELAY '00:00:10' PRINT 'Продолжение после первой паузы на 10 сек. Сейчас' + CONVERT (VARCHAR(20),GETDATE()) WAITFOR TIME '01:20' PRINT 'Продолжение после второй паузы. Сейчас' +CONVERT VARCHAR(20),GETDATE()) Курсоры. Для работы с курсорами используются следующие операторы (см.табл.9): Таблица 9. Операторы по работе с курсорами в Transact SQL Оператор DECLARE CURSOR OPEN Описание Создает курсор Открывает курсор МЕЖДУНАРОДНЫЙ БАНКОВСКИЙ ИНСТИТУТ INTERNATIONAL BANKING INSTITUTE Выбирает данные Закрывает ранее открытый курсор Уничтожает ранее созданный курсор Оператор DECLARE CURSOR – определяет выполняемый запрос, задает имя курсора и связывает результаты запроса с заданным курсором. Этот оператор не является исполняемым для запроса, он только определяет структуру будущего множества записей и связывает ее с уникальным именем курсора. Этот оператор подобен операторам описания данных в языках программирования. Оператор OPEN – дает команду СУБД выполнить описанный запрос, создать виртуальный набор строк, который соответствует заданному запросу. Оператор OPEN устанавливает указатель записей (курсор) перед первой строкой виртуального набора строк результата. Оператор FETCH продвигает указатель записей на следующую позицию в виртуальном наборе записей. В большинстве коммерческих СУБД оператор перемещения FETCH реализует более широкие функции перемещения, он позволяет перемещать указатель на произвольную запись, вперед и назад, допускает как абсолютную адресацию, так и относительную адресацию, позволяет установить курсор на первую или последнюю запись виртуального набора. Оператор CLOSE закрывает курсор и прекращает доступ к виртуальному набору записей. Он фактически ликвидирует связь между курсором и результатом выполнения базового запроса. Однако в коммерческих СУБД оператор CLOSE не всегда означает уничтожение виртуального набора записей. Мы коснемся этого далее. Когда будем рассматривать работу с курсором в MS SQL Server 2000. При использовании оператора CLOSE структура данных остается доступной для повторного открытие. Оператор DEALLOCATE - удаляет взаимосвязь между курсором и именем курсора или переменной курсора. Если имя или переменная являются последними, ссылающимися на курсор, все ресурсы, выделенные курсору, освобождаются. Курсор объявляется оператором DECLARE: DECLARE <имя_курсора> CURSOR [ LOCAL | GLOBAL ] [ FORWARD_ONLY | SCROLL ] [ STATIC | KEYSET | DYNAMIC | FAST_FORWARD ] [ READ_ONLY | SCROLL_LOCKS | OPTIMISTIC ] [ TYPE_WARNING ] FETCH CLOSE DEALLOCATE МЕЖДУНАРОДНЫЙ БАНКОВСКИЙ ИНСТИТУТ INTERNATIONAL BANKING INSTITUTE FOR <оператор выбора SELECT> [ FOR UPDATE [ OF <имя_столбца 1> [ ,...n ] ] ] Здесь Опция LOCAL говорит о том, что курсор является локальным для того блока (пакета, хранимой процедуры или триггера), в котором он определен. По окончании работы этого блока курсор будет неявно уничтожен. Опция GLOBAL является противоположностью опции LOCAL. Она говорит, что объявленный курсор продолжает существовать и по окончании блока в котором он был создан, если только он не был удален явно. По умолчанию используются установки сервера для конкретной БД. SCROLL - определяет, что допустимы любые режимы перемещения по курсору (FIRST, LAST, PRIOR, NEXT, RELATIVE, ABSOLUTE) в операторе FETCH. Если не указано ключевое слово SCROLL, то считается доступной только стандартное перемещение вперед спецификация NEXT в операторе FETCH. FORWARD_ONLY – это опция являющаяся противоположностью опции SCROLL, описанной выше и говорит что для перемещению по курсору можно использовать только опцию NEXT команды FETCH. STATIC – определяет режим создания набора строк, соответствующего определяемому курсору, при котором при открытии курсора все данные, на которых он строятся копируются во временную таблицу в БД tempdb. Таким образом, все изменения в исходных таблицах, произведенные после открытия курсора другими пользователями, не видны в нем. Такой набор данных нечувствителен ко всем изменениям, которые могут проводиться другими пользователями в исходных таблицах, этот тип курсора соответствует некоторому мгновенному слепку с БД. Поскольку данные копируются во временную таблицу, такой курсор не позволяет делать изменений в данных на которых он строится. KEYSET - при использовании этой опции в момент открытия курсора во временной таблице будет создан набор ключей набора строк, получаемого при помощи оператора выбора SELECT. В дальнейшем при перемещении по курсору будет происходить перемещение по ключам из временной таблицы, а остальные поля будут браться из исходных полей. Такой подход позволит лучше отслеживать изменения, сделанные с момента открытия курсора. Однако, это не позволит отследить все изменения. DYNAMIC – при указании этой опции в курсоре будут отображаться МЕЖДУНАРОДНЫЙ БАНКОВСКИЙ ИНСТИТУТ INTERNATIONAL BANKING INSTITUTE все изменения, сделанные с момента открытия курсора. При ее использовании недоступна опция ABSOLUTE команды FETCH. FAST_FORWARD – по сути обозначает совокупность опций FORWARD_ONLY и READ_ONLY с добавлением оптимизации производительности. Эта опция несовместима с опциями SCROLL, FOR_UPDATE и FORWARD_ONLY. READ ONLY - изменения и обновления исходных таблиц не будут выполняться с использованием данного курсора. Курсор с данной спецификацией может быть самым быстры в обработке. SCROLL_LOCKS – гарантирует возможность удаления и изменений строки на которую в данный момент указывает курсор. При позиционировании на какую-либо строку при указании этой опции, активная строка блокируется, и никто не сможет ничего с ней сделать после того, как строка была прочитана в курсор и до того момента как она будет освобождена (при переходе на другую строку или закрытии курсора). OPTIMISTIC – При указании этой опции, при чтении строки в курсор, ее блокировка не производится. TYPE_WARNING – при задании этой опции, пользователю могут быть выданы специальные сообщения о некоторых нарушений. FOR UPDATE [OF <имя столбца 1> [,...<имя столбца n>]] мы задаем перечень столбцов, в которых допустимы изменения в процессе нашей работы с курсором. Такое ограничение упростит и ускорит работу СУБД. Пример: Опишем курсор, который содержит список должников нашей библиотеки. Мы не собираемся использовать данный курсор для удаления или обновления строк. Поэтому мы его определили как курсор только для чтения. declare Deptor Cursor Local for select distinct NUM_reader from exemplar Where Yes_NO ='0' and Data_RETURN < Getdate() FOR READ ONLY Оператор открытия курсора имеет следующий синтаксис OPEN {{[ GLOBAL ] <имя_курсора> } | | <имя переменной типа курсор> } Именно оператор открытия курсора инициирует выполнение базового запроса, соответствующего описанию курсора, заданному в операторе DECLARE … CURSOR. SQL Server возвращает код завершения операции в специальной системной переменной @@Error. При неудачном выполнении МЕЖДУНАРОДНЫЙ БАНКОВСКИЙ ИНСТИТУТ INTERNATIONAL BANKING INSTITUTE операции открытия курсора СУБД возвращает ненулевое значение @@Error. После того, как курсор открыт, в системной переменной @@Cursor_Rows будет содержаться количество строк в открытом курсоре. После открытия указатель текущей строки установлен перед первой строкой курсора. Стандартно оператор FETCH перемешает указатель текущей строки на следующую строку и присваивает базовым переменным значение столбцов, соответствующее текущей строке. Оператор FETCH имеет следующий синтаксис: FETCH [NEXT | PRIOR | FIRST | LAST | ABSOLUTE {n | <имя_переменной>} | RELATIVE{n|<имя_переменной>}] FROM { { [ GLOBAL ] <имя курсора> } | <имя переменно типа курсор> } INTO <список базовых переменных> Здесь параметр NEXT задает выбор следующей строки после текущей из базового набора строк, связанного с курсором. Параметр PRIOR задает перемещение на предыдущую строку по отношению к текущей. Параметр FIRST задает перемещение на первую строку набора, а параметр LAST задает перемещение на последнюю строку набора, ABSOLUTE, задает номер конкретной строки, параметр RELATIVE задает относительный адрес. При абсолютной адресации отрицательное число будет трактоваться как n-ая строка от конца набора данных; в случае же 0 в качестве параметра, данные вообще не будут возвращены. При относительной адресации положительное число сдвигает указатель в низ от текущей записи, отрицательное число сдвигает вверх от текущей записи. В случае, если число отрицательное или 0 при первом вызове, то никаких данных возвращено не будет. После каждого выполнения оператора FETCH изменятся состояние системной переменной @@Fetch_status. Эта переменная показывает результат работы оператора. Переменная может иметь три состояния (см. таб.10): Таблица 10. . Значение глобальной переменной @@Fetch_status при работе с курсором Значение Описание переменной 0 Оператор выполнен успешно. В переменные МЕЖДУНАРОДНЫЙ БАНКОВСКИЙ ИНСТИТУТ INTERNATIONAL BANKING INSTITUTE занесены значения из очередной строки набора данных -1 Строки в наборе данных закончились или же затребованная строка находится вне его пределов, либо же произошла ошибка при выполнении оператора -2 Строки в наборе данных нет. Это значение может получиться в том случае, когда определена опция KEYSET курсора. В этом случае при открытии во временную таблицу копируются ключи набора данных, а все остальные значения получаются путем обращения к реальным таблицам по известным ключам при выполнении Fetch. Если после открытия курсора строка, вошедшая в набор (ключ ее скопирован во временную таблицу) была удалена, либо же ее ключ изменен, то найти строку по заданному ключу будет невозможно. В этом случае будет выдан код -2 в переменную @@Fetch_status Следует помнить, что переменная @@Fetch_Cursor – глобальная, т.е. если существует несколько вложенных курсоров, то значение @@Fetch_Cursor будет относиться к тому из них, для кого выполнен оператор FETCH. Оператор закрытия курсора Оператор закрытия курсора имеет простой синтаксис, он выглядит следующим образом: CLOSE {{[ GLOBAL ] <имя_курсора> } | | <имя переменно типа курсор> } Оператор закрытия курсора освобождает память, используемую под данные набора данных курсора и снимает наложенные на данные блокировки. При этом сама структура курсора, т.е. его описание остается доступным. Т.е. можно вновь открыть курсор без того, чтобы его вновь описывать. Оператор уничтожения курсора Наряду с оператором закрытия курсора используется оператор его уничтожения: DEALLOCATE {{[ GLOBAL ] <имя_курсора> } | | <имя переменно типа курсор> } При выполнении оператора DEALLOCATE SQL Server освобождает разделяемую память, используемую командой описания МЕЖДУНАРОДНЫЙ БАНКОВСКИЙ ИНСТИТУТ INTERNATIONAL BANKING INSTITUTE курсора DECLARE. После выполнения этой команды невозможно выполнение команды OPEN для данного курсора. Задание 1. В учебной БД «Библиотека» создать глобальный курсор, который будет содержать список названий всех книг, которые имеются в библиотеке. Открыть курсор и при перемещении по нему каждый раз считать и выводить на экран общее количество экземпляров данной книги в библиотеке и количество свободных экземпляров книги в данный момент. При выполнении задания помним, что переменная @@fetch_status появляется только после того, как Вы выполнили хотя бы одну операцию Fetch для курсора. Количество экземпляров книг все и тех, что на руках Вы можете сосчитать стандартными SQLзапросами, а данные поместить в локальные переменные. Не забудьте закрыть курсор и уничтожить его. Задание 2. Добавьте столбец «Cost» - стоимость книги в таблицу «Books» и заполните его для всех книг. Создайте курсор, который выводит список читателей. Перемещаясь по курсору выведите для каждого читателя количество книг, находящихся на руках с указанием общей их стоимости.