Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
мет_ОБД.doc
Скачиваний:
1
Добавлен:
01.03.2025
Размер:
1.92 Mб
Скачать

Instead of delete

not for replication

as

begin

declare

@var int

set @var = (select [object_id] from sys.objects where

name = 'trig2'and TYPE = 'TR'

and schema_id = (select schema_id from sys.schemas

where name = 'dbo'

)

)

if (TRIGGER_NESTLEVEL(@var, 'IOT', 'DML') = 1)

begin

delete from table1 from deleted d where table1.c3 = d.c3

end

end

go

Оскільки тригер INSTEAD OF спрацьовує замість команди DELETE, то дані з таблиці table1 віддалятися не будуть. Для того щоб їх видалити (видаляються дані, що, зберігаються в спеціальній таблиці deleted), необхідно повторити цю дію в тілі тригера. Як і в минулому прикладі, максимальна кількість рекурсивних викликів цього тригера = 2.

У результаті виконання команди:

delete table1 where c1 = 2

що приведе до спрацьовування тригера trig2, таблиця table1 буде містити наступні дані:

c1

c2

c3

1

1

1

1

2

2

1

3

3

1

4

4

6

5

6

Приклад 3.

Створення найпростішого INSTEAD OF тригера, що спрацьовує при виконанні всіх трьох команд (INSERT, UPDATE, DELETE) і, визначаючи тип команди, повторює дії, які команда повинна була виконати над даними таблиці.

if exists(select * from sys.objects where name = 'trig3' and schema_id = (select schema_id from sys.schemas where name = 'dbo') and type = 'TR')

drop trigger trig3

go

create trigger trig3

on table1

Instead of insert, update, delete

not for replication

as

begin

/*

Установка noucount on приводить до того, що не виводиться кількість оброблених командами T-SQL рядків

*/

set nocount on

declare

@var int

set @var = (select [object_id] from sys.objects where name = 'trig3'

and TYPE = 'TR'

and schema_id = (select schema_id from sys.schemas

where name = 'dbo')

)

if (TRIGGER_NESTLEVEL(@var, 'IOT', 'DML') = 1)

begin

declare

@count1 int,

@count2 int,

@count3 int,

@col_upd varbinary(128)

set @count1 = (select count(*) from table1)

set @count2 = (select count(*) from inserted)

set @count3 = (select count(*) from deleted)

set @col_upd = columns_updated()

if (@col_upd != 0)

begin

if (@count2 = @count3)

begin

- Випадок, коли тригер активований командою UPDATE

declare

@col_name varchar(128),

@table_id int,

@col_id int,

@is_iden bit,

@is_comp bit,

@type_id tinyint,

@type_name sysname

- одержуємо ідентифікатор таблиці table1 із системеного подання sys.objects

set @table_id = (select [object_id] from sys.objects where

name = 'table1' and type = 'U' and

schema_id = (select [schema_id]

from sys.schemas where name = 'dbo')

)

set @col_id = 0

/*

При використанні команди EXECUTE не можна звертатися до таблиці inserted, тому копіюємо її вміст у тимчасову таблицю

*/

select * into #temp_ins from inserted

- відключаємо спрацьовування тригера trig3

alter table table1 disable trigger trig3

- запускаємо цикл по тимі стовпцям, значення яких змінювалися

while (@col_upd <> 0)

begin

- одержуємо поточний номер стовпця один по одному від початку таблиці

set @col_id = @col_id + 1

if ((@col_upd & 1) = 1)

begin

- якщо цей стовпець піддавався зміні

/*

Одержуємо назву цього стовпця, інформацію про те, чи має він властивість identity або чи є він таким, що обчислюється або чи має він властивість identity, і ідентифікатор системного типу даних для цього стовпця

*/

select @col_name = name, @is_iden = is_identity,

@is_comp = is_computed,

@type_id = system_type_id

from sys.columns where

([object_id] = @table_id)

and (column_id = @col_id)

- Якщо стовпець не має властивості idenity і не є що обчислюється

if ((@is_iden <> 1) and (@is_comp <>1))

begin

- Одержуємо назву типу даних для цього стовпця

set @type_name = (select name from sys.types

where system_type_id = @type_id)

/*

Використовуючи команду EXECUTE і конструювання пакета SQL команд у строковому виді за допомогою операції конкатенації рядків виконуємо наступні дії:

  1. Оголошуємо курсор по таблиці #temp_ins, що зберігає змінені значення оброблюваного стовпця і значення первинного ключа.

  2. Оголошуємо змінні, які будуть використовуватися при одержанні значень поточного рядка курсору.

  3. Запускаємо цикл, у якому перебираємо по черзі всі рядки курсору.

  4. У цьому циклі одержуємо значення зміненого стовпця для поточного рядка, а також значення первинного ключа і конструюємо відповідну команду update, що для оброблюваного стовпця змінює його значення на отримане при збігу первинних ключів.

  5. По закінченні циклу закриваємо курсор.

Для таблиць, де можлива зміна первинного ключа потрібен більш складний алгоритм, тому що змінюваний стовпець може виявитися елементом первинного ключа.

*/

execute( 'declare cur_ins cursor local for

select ' + @col_name +

' from #temp_ins ' +

'open cur_ins ' +

'declare @value_new ' + @type_name + ', ' +

' @value_key int '+

'while (1 = 1) ' +

'begin ' +

' fetch next from cur_ins into @value_new ,

@value_key' +

' if (@@FETCH_STATUS = -1) ' +

break; ' +

' update table1 set ' + @col_name + ' =

@value_new where c3 = @value_key ' +

'end ' +

'close cur_ins '

);

end

end

- Переходимо до обробки наступного стовпця

set @col_upd = @col_upd / 2

end

-- Знову дозволяємо спрацьовування тригера

begin

enable trigger trig3 ON table1

end

end

else

if (@count3 = 0)

begin

- Тригер активований командою INSERT