tsql

33
eleks.com eleks.com Розширення SQL Transact SQL Програмні конструкції T-SQL Процедури та функції Обробка помилок Курсори, тимчасові таблички Динамічний SQL Транзакції Тригери

Upload: eleksdev

Post on 10-Feb-2017

1.297 views

Category:

Technology


0 download

TRANSCRIPT

Page 1: tsql

eleks.com eleks.com

Розширення SQLTransact SQL

• Програмні конструкції T-SQL• Процедури та функції• Обробка помилок• Курсори, тимчасові таблички• Динамічний SQL• Транзакції• Тригери

Page 2: tsql

Програмні конструкції T-SQL•Блок-оператор BEGIN {множина операторів} END•Умовний оператор IF {логічний вираз} {1 оператор}[ELSE {1

оператор}]

•Оператор циклу WHILE {логічний вираз} {1 оператор [BREAK][CONTINUE]}

•Оператор зупинки RETURN [ціле число] – повертає стан виконання блоку (0 - success)

•Оператор переходу GOTO мітка – в якому сама мітка має вигляд point:

•Конструкція виконання BEGIN TRY {1 оператор} END TRY

BEGIN CATCH {1 оператор} END CATCH

Page 3: tsql

•Оператор затримки WAITFOR{DELAY[проміжок часу]|TIME[значення типу datetime][,TIMEOUT затримка]}

•Оператор виконання EXECUTE {}• Оголошення (команда DECLARE)

• Присвоєння значень оператор SELECT (можна кільком змінним відразу та використанням джерела даних) або оператор SET

• GO [кількість повторень] – інформує SQL сервер про закінчення пакету інструкцій

Програмні конструкції T-SQL

Page 4: tsql

Процедура (Stored Procedure)Процедури – об’єкт БД, який дозволяє виконувати набір інструкцій

•Керуються операторами CREATE, ALTER та DROP•Допускають наявність параметрі•Можуть повертати значення різними способами:

-OUTPUT параметри-RETURN - коди (лише int значення)-Result Set кожного SELECT’у чи іншої процедури,

викликаної всередині-Через глобальний курсор, оголошений за межами

процедури

Page 5: tsql

Приклад процедуриCREATE PROCEDURE RecalculateBoxOffice

@MovieId intASBEGIN

UPDATE MovieSET BoxOffice = (select sum(cs.profit) from CinemaShow cswhere ca.MovieId = MovieId)WHERE MovieId = @MovieId

ENDGO

Дану процедуру можна викликати наступним чином :exec RecalculateBoxOffice 1

Page 6: tsql

Виклик процедури з іншого пакету:begindeclare @mId intset @mId = 2exec RecalculateBoxOffice @MovieId = @mIdselect BoxOffice from Moviewhere MovieId = @mIdendGO

Оголошення параметру із значенням по замовчуванню:ALTER PROCEDURE RecalculateBoxOffice @MovieId int = 0AS…

Приклад процедури

Page 7: tsql

Перевірка параметрів:ALTER PROCEDURE RecalculateBoxOffice@MovieId int = 0,@UpdatedBoxOffice money OUTPUTASdeclare @err_code intBEGINdeclare @mId intset @mId = isnull( @MovieId, 0)if @mId = 0 -- check input parameterbeginraiserror('Parameter MovieId is empty!', 10, 1)set @err_code = 50001end

Обробка помилок

Page 8: tsql

Перевірка наявності значення:-- check exists needed rowsif not exists(select 1 from Movie

where MovieId = @mId)beginraiserror('Parameter MovieId %d not found!', 10, 1, @mId)set @err_code = 50002goto SP_ENDend-- update tableUPDATE MovieSET BoxOffice = (select sum(cs.Profit) from CinemaShow cswhere cs.MovieId = MovieId)WHERE MovieId = @mId

Обробка помилок

Page 9: tsql

Перевірка виконання оператора:select @row_code = @@ROWCOUNT, @err_code = @@ERRORif @err_code <> 0 -- check errorbeginraiserror(‘BoxOffice was not calculated for %d!',10,1,@mId)goto SP_ENDendif @row_code = 0 -- check update resultsbeginraiserror(‘Nor rows was updated for %d!',10,1,@ mId)set @err_code = 50003goto SP_ENDend

Обробка помилок

Page 10: tsql

Використання конструкції TRY…CATCH :BEGIN TRY -- update table

UPDATE MovieSET BoxOffice = (select sum(cs.Profit)

from CinemaShow cswhere cs.MovieId = MovieId)

WHERE MovieId = @MovieId END TRYBEGIN CATCH -- check error

SELECT ERROR_NUMBER() ErrorNumber, ERROR_SEVERITY() ErrorSeverity, ERROR_STATE() ErrorState, ERROR_PROCEDURE() ErrorProcedure, ERROR_LINE() ErrorLine, ERROR_MESSAGE() ErrorMessage;END CATCH

Обробка помилок

Page 11: tsql

Обробка помилокПовернення результату із процедури :

-- return new valueselect @UpdatedBoxOffice = BoxOffice from Moviewhere MovieId = @mIdreturn 0SP_END:return @err_codeENDGO

Виклик процедури:declare @ResultValue money = 0declare @ResultCode int = 0exec @ResultCode = RecalculateBoxOffice @MovieId = 1, @UpdatedBoxOffice = @ResultValue OUTPUT

select @Res, @Amm

Page 12: tsql

Використання курсору

Обробка множини значень:declare @Amount intdeclare @Price moneyset @Amount = 0declare docDet cursor -- init cursor

FORWARD_ONLY FAST_FORWARD READ_ONLY LOCALfor select Amount, Price

from DocumentDetail where DocumentId = @DocumentIdopen documentDetail -- open cursor for usingfetch next from docDet into @Amount, @Price -- use cursorwhile @@FETCH_STATUS = 0begin

set @Amount = @Amount + @Amount * @Pricefetch next from docDet into @Amount, @Price

endclose docDet -- close cursordeallocate docDet-- free cursor

Page 13: tsql

Використання курсоруТип доступу до курсору LOCAL | GLOBAL Варіанти руху по курсору FORWARD_ONLY | SCROLLСпосіб вичитування до даних

STATIC | KEYSET | DYNAMIC | FAST_FORWARD Варіанти блокування даних під час використання курсору

READ_ONLY | SCROLL_LOCKS | OPTIMISTIC Видавати попередження про неузгодженість типів у курсорі

TYPE_WARNINGЗміна значень в курсорі (або в його окремих колонках)

FOR UPDATE [ OF назви колонок]

Page 14: tsql

Використання курсоруОператор отримання строки з курсору - FETCHFETCH FIRST – отримання першого рядкаFETCH LAST – отримання останнього рядкаFETCH ABSOLUTE – отримання рядка за його порядковим номеромFETCH RELATIVE – використовується для переміщення курсору вперед чи назад на задану кількість рядківFETCH PRIOR – отримання попереднього рядкаFETCH NEXT – отримання наступного рядка (за замовчуванням)

Для варіанту руху FORWARD_ONLY доступний лише FETCH NEXT

Page 15: tsql

Використання тимчасових таблиць

Змінні табличного типу:declare @TempTab table (

Amount int,Price money)

-- insert datainsert into @TempTab (Amount, Price)

select Amount, Pricefrom DocumentDetail where DocumentId = @DocumentId

-- use tableselect @Amount = sum(Amount * Price)

from @TempTab

Page 16: tsql

Використання тимчасових таблиць

Локальні тимчасові таблиці:create table #TempTab (Amountint,Price money)insert into #TempTab (Amount, Price)select Amount, Pricefrom DocumentDetailwhere DocumentId = @DocumentIdselect @Amount = sum(Amount * Price)from #TempTabdrop table #TempTab

Глобальні тимчасові таблиці (##) доступні всім сесіям та процесам

Page 17: tsql

Динамічний SQL (Dynamic SQL) Безпосереднє виконання запитів із стрічки:

exec ('select Name from Client')declare @query varchar(50)set @query = 'select Name from Client ' +

' where ClientId = ' + cast(1 as varchar(2))exec (@query)

Використання процедури sp_executesql:DECLARE @intParameter INTDECLARE @query NVARCHAR(500) -- Build the SQL stringDECLARE @parameterDef NVARCHAR(100) -- Specify the parameter formatSET @query = N'select Name from Client where ClientId = @ClientId'SET @parameterDef = N'@ClientId int'SET @intParameter = 1; -- Execute with the first parameter valueEXECUTE sp_executesql @query, @parameterDef, @ClientId = @intParameterSET @IntParameter = 2; -- Execute the same with the second valueEXECUTE sp_executesql @query, @ParameterDeg, @ClientId = @intParameter

Page 18: tsql

SQL-ін’єкції

Page 19: tsql

ФункціїСкалярні функції, визначені користувачем:

CREATE FUNCTION GetCinemaProfitSum(@MovieId int = 0)RETURNS moneyASBEGINdeclare @result moneyselect @result = sum(Profit) from CinemaShow where MovieId = @MovieIdreturn @resultENDGO

Приклад використання:select dbo. GetCinemaProfitSum(1)

Page 20: tsql

ФункціїПерелік дозволених операторів (виразів) у функціях:• Оператор присвоєння (SELECT, SET)• Всі оператори керування послідовністю дій (if, while, goto, …), окрім

TRY...CATCH виразу.• DECLARE - вирази для оголошення локальних змінних та курсорів• SELECT - вирази повинні повертати данні у змінні • Всі операції з локальними курсорами (OPEN, FETCH, CLOSE,

DEALLOCATE) повинні знаходитися всередині функції, також FETCH - вираз може бути використаний лише для присвоєння значення локальним змінним

• INSERT, UPDATE та DELETE повинні модифікувати лише локальні змінні типу table.

• Оператор EXECUTE викликає лише загальні процедури

Page 21: tsql

ФункціїТабличні функції, визначені користувачем:

CREATE FUNCTION fnClientList(@c_Name varchar(20))RETURNS @resList table (cfName varchar(50))

ASBEGIN

declare @nInt intdeclare @cName varchar(50)set @nInt = 1while @nInt > 0 begin

select top 1 @cName = cName from tClients where cName like (@c_Name + '%')and cName not in (select cfName from @resList)

set @nInt = @@rowcountif @nInt > 0

insert into @resList(cfName) values (@cName)endreturn

ENDGO

Приклад використання:select * from dbo.fnClientList('CL')

Page 22: tsql

Задані користувачем типи•User-defined Data Types•User-defined Table Types

Створення Table типу:create type EmailTable as table(

EmailId int null,EmailAddress nvarchar(256) not null,EmailTypeEnum int not null,IsPrimary bit not null

)

Використання параметром в процедурі:create procedure CreateContact

@FirstName nvarchar(64),@LastName nvarchar(64),@Emails EmailTable readonly,@Phones PhoneTable readonly

as begin--procedure body

end

Page 23: tsql

ТранзакціїОкрема операція або набір операцій, які розглядаються як єдиний ланцюжок дійТранзакція має чотири спеціальні характеристики (властивості ACID):1. Неподільність (ATOMIC) – зв’язані операції можуть

виконуються або всі, або не виконується жодна2. Відповідність (CONSISTENCY) – по закінчені транзакції всі

данні повинні відповідати всім правилам, які накладаються на них в БД, без винятків

3. Ізоляція (ISOLATION) – одна транзакція не може накладатися на іншу (перетинатися з іншою)

4. Довговічність (DURABILITY) – після завершення транзакції всі внесені зміни повинні стати постійними

Page 24: tsql

Транзакції

Чотири режими транзакцій:1. Autocommit (автоматична фіксація транзакцій) – використовується по

замовчуванню, ініціюються SQL-сервером для кожної команди зокрема2. Explicit (явно задані транзакції) – ініціюються та керуються користувачем за

допомогою наступних команд:• BEGIN {TRAN | TRANSACTION} [назва транзакції]• COMMIT {TRAN | TRANSACTION} [назва транзакції]• ROLLBACK {TRAN | TRANSACTION} [назва транзакції]• SAVE {TRAN | TRANSACTION} [назва точки збереження]3. Implicit (неявні транзакції) – режим автоматичної ініціалізації транзакції,

проте явного примусового завершення (регулюється перемикачем SET IMPLICIT_TRANSACTIONS { ON | OFF })

4. Batch-scored (транзакції для виконання пакетів) – специфічний режим для однієї сесії Multiple Active Result Sets (MARS)

Page 25: tsql

Рівні ізольованості транзакцій:Проблеми паралельного виконання транзакцій:

•Втрачене обновлення (lost update)•«Брудне» читання (dirty read)•Неповторюване читання (non-repeatable read)•Фантомне читання (phantom reads)

Встановлення рівня ізоляції:SET TRANSACTION ISOLATION LEVEL [LEVELNAME]

Page 26: tsql

Рівні ізольованості транзакцій:1.Read uncommitted2.Read committed (рівень за замовчуванням в MSSQL)3.Repeatable read4.Serializable

Поведінка при різних рівнях ізольованості:

Рівень ізоляції Втрачене оновлення

«Брудне» читання

Неповторюване читання

Фантомне читання

Read uncommitted + - - -

Read committed + + - -

Repeatable read + + + -

Serializable + + + +

Page 27: tsql

ТранзакціїПриклад транзакції в процедурі:

CREATE PROCEDURE InsertDocumentDetails@DocId int, @ProductId int, @Amount int, @Price money, @DocDetailId int OUTPUTAS…--BEGIN TRYBEGIN TRAN T1INSERT INTO DocumentDetail(DocumentId,ProductId,Amount,Price)VALUES (@Docid,@ProductId,@Amount,@Price)set @DocDetailId = @@IDENTITYUPDATE DocumentSET Amount = Amount + @Amount * @Price

WHERE DocumentId = @DocIdCOMMIT TRAN T1END TRYBEGIN CATCHROLLBACK TRAN T1set @DocDetailId = 0END CATCH--

Page 28: tsql

ТранзакціїОсобливості використання вкладених транзакційСистемна функція @@TRANSCOUNT (BEGIN TRANSACTION збільшує значення цієї змінної на 1, а оператор COMMIT TRANSACTION – зменшує 1)Оператор SAVE TRANSACTION (фіксує певні змін і дає можливість відкочувати стан даних саме до цієї точки)

Відображення впливу всіх операторів на @@TRANSCOUNT:Оператор Вплив

BEGIN TRANSACTION +1COMMIT TRANSACTION -1ROLLBACK TRANSACTION Встановить 0SAVE TRANSACTION “мітка” Без змінROLLBACK TRANSACTION “мітка” Без змін

Page 29: tsql

ТранзакціїПриклад вкладених транзакцій #1:

CREATE PROCEDURE InsertDocumetDetailsTR@DocumentId int, @ProductId int, @Amount int, @Price money,@DocDetailId int OUTPUTASBEGINdeclare @Sum moneydeclare @Res intBEGIN TRYBEGIN TRAN T1 -- begin main tranINSERT INTO DocumentDetail (DocumentId, ProductId, Amount, Price)VALUES (@DocumentId,@ProductId,@Amount,@Price)set @DocumentDetailId = @@IDENTITYset @Sum = @Amount * @Price-- run other procedure

exec @Res = UpdateDocumentTR @DocumentId, @Sum

Page 30: tsql

Приклад вкладених транзакцій #2:CREATE PROCEDURE UpdateDocumentTr

@DocumentId int, @Sum moneyASBEGIN

declare @tranCount int -- choose value before begin our transactionsselect @tranCount = @@TRANCOUNTBEGIN TRYif @tranCount = 0begin tran tr2 -- begin tran for separate modeelsesave tran tr2 -- start save for call modeupdate Documentset Amount = Amount + @Sumwhere DocumentId = @Docif @tranCount = 0 –– commit tran only for separate modecommit tran tr2return 0END TRYBEGIN CATCHrollback tran tr2 –– rollback new tran only return 50010 –– return error codeEND CATCH

END

Транзакції

Page 31: tsql

ТригерТип процедур, який виконується автоматично як частина оператора по зміні даних. Trigger DML створюється для таблиці і зв’язується з однією або кількома подіями модифікації даних (INSERT, UPDATE, DELETE).Основними властивостями тригера можна назвати:

•Можливість порівняння попередньої та наступної версії даних (системні таблиці deleted та inserted)

•Здійснення при потребі відкоту недопустимих змін•Зчитування та зміна даних в інших таблицях•Виконання процедур та функцій

•Функція update() дозволяє перевірити зміну колонки таблички (задається як параметр)

Page 32: tsql

ТригерПриклад тригера:

CREATE TRIGGER DocumentDetailSumON DocumentDetail AFTER INSERT,UPDATE,DELETEASdeclare @oldDocumentId int, @newDocumentId int, @DocumentId intdeclare @oldSum money, @newSum money, @Sum moneyBEGINif update(Price) or update(Amount)beginselect @oldDocumentId=DocumentId, @oldSum=Price*Amountfrom deletedselect @newDocumentId=DocumentId, @newSum=Price*Amountfrom insertedselect @DocumentId = isnull(@oldDocumentId,@newDocumentId),@Sum = isnull(@newSum,0) - isnull(@oldSum,0)exec UpdateDocument @DocumentId, @SumendEND

Page 33: tsql

Any questions?