Гость
Форумы / Microsoft SQL Server [игнор отключен] [закрыт для гостей] / Консультация по тригерам. / 7 сообщений из 7, страница 1 из 1
29.04.2020, 20:07
    #39953058
Frankestein
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Консультация по тригерам.
Добрый вечер.

Больше недели пытаюсь разобраться с тригерами, но к сожалению безуспешно.
Есть таблица
Код: sql
1.
dbo.sotr_project (code_employer,code_project)

. Создал две таблицы для аудита.
Код: sql
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
Create tableAudit_operations
(
[Номер операции] int  Primary key Identity(1,1),
[Вид операции] varchar(50)  CHECK
        ([Вид операции] IN ('Изменение', 'Добавление', 'Удаление')), 
[Время операции] datetime
)
go
Create table Audit_sort_project
(
[Номер изменения] int  Primary key Identity(1,1),
[Номер операции] int,
[Шифр сотрудника] int,
[Старый шифр проекта] int, 
[Новый шифр проекта] int
)


Написал тригер для таблицы.
Код:
Код: sql
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
create trigger  sotr_projectTriger on dbo.sotr_project
after UPDATE, INSERT, DELETE
as
declare @dateNow datetime,@activity varchar(20),@numberOperation int,@numberEmployers int,@oldCodeProject int,@newCodeProject int, @ident int, @idCodeEmployer int, @idVid  int;
Set @dateNow =GETDATE();
if exists(SELECT * from inserted) and exists (SELECT * from deleted)
begin
    SET @activity = 'Изменение';
	INSERT into Audit_operations([Вид операции],[Время операции]) values(@activity,@dateNow);
--дописать
end
If exists (Select * from inserted) and not exists(Select * from deleted)
begin
    SET @activity = 'Добавление';
	INSERT into Audit_operations([Вид операции],[Время операции]) values(@activity,@dateNow);
	Select @idCodeEmployer = inserted.code_employer from inserted
	Select @idVid = (Select scope_identity() from Audit_operations)
	Insert into Audit_sort_project([Номер операции], [Шифр сотрудника], [Старый шифр проекта], [Новый шифр проекта]) values
	(@idVid,@idCodeEmployer, 111,111)
end
If exists(select * from deleted) and not exists(Select * from inserted)
begin 
    SET @activity = 'Удаление';
	INSERT into Audit_operations([Вид операции],[Время операции]) values(@activity,@dateNow);
end


Добавляю значение в таблицу
Код: sql
1.
2.
3.
Insert into dbo.sotr_project (code_employer,code_project)
values
(52,62)


Всё успешно.
При попытке другого добавления выходит ошибка.
Код: sql
1.
2.
3.
Insert into dbo.sotr_project (code_employer,code_project)
values
(53,63)


Вложенный запрос вернул больше одного значения. Это запрещено, когда вложенный запрос следует после =, !=, <, <=, >, >= или используется в качестве выражения.
Интернет проверял, но везде примеры добавления одного значения в таблицу при помощи IDENT_CURRENT, @@IDENTITY и SCOPE_IDENTITY, а у меня добавления двух значений. Из-за чего и выходит ошибка.

Помогите разобраться, пожалуйста.
...
Рейтинг: 0 / 0
29.04.2020, 22:25
    #39953104
felix_ff
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Консультация по тригерам.
Frankestein,

У Вас проблема вот тут:

Код: sql
1.
Select @idVid = (Select scope_identity() from Audit_operations)



на момент второго срабатывания в триггере записей в Audit_operations будет больше 1, соответственно присваивание множественных значений переменной не допустимо.

это равносильно такому: сравните два запроса:
Код: sql
1.
2.
declare @id int;
select @id = ( select id from (values (1)) T(id));



Код: sql
1.
2.
declare @id int;
select @id = ( select id from (values (1), (2), (3)) T(id));



первый не ругнется потому что только одна строка, второй ругнется потому что строк 3 а переменная одна.

что бы выбирать последнее значение identity вам не нужно его селектить из таблицы это функция возвращающая скалярное значение.
достаточно просто присвоить ее результат переменной:

Триггер должен выглядеть как то так:

Код: sql
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
36.
37.
38.
39.
40.
41.
42.
43.
44.
45.
46.
47.
48.
49.
50.
51.
52.
53.
CREATE TRIGGER [sotr_projectTriger] ON [dbo].[sotr_project] AFTER UPDATE, INSERT, DELETE
AS
IF @@OPTIONS & 512 = 0 SET NOCOUNT ON;

DECLARE
       @dateNow DATETIME,
       @activity VARCHAR(20),
       @numberOperation INT,
       @numberEmployers INT,
       @oldCodeProject INT,
       @newCodeProject INT,
       @ident INT,
       @idCodeEmployer INT,
       @idVid INT,
       @iflag BIT,
       @dflag BIT;

SET @dateNow = GETDATE();

SET @iflag = 0;
IF EXISTS (SELECT 1 FROM INSERTED) SET @iflag = 1;

SET @dflag = 0;
IF EXISTS (SELECT 1 FROM DELETED) SET @dflag = 1;

IF @iflag = 1 and @dflag = 1
BEGIN
    SET @activity = 'Изменение';

    INSERT INTO [dbo].[Audit_operations] ([Вид операции],[Время операции]) VALUES (@activity, @dateNow);
--дописать
END
ELSE IF @iflag = 1 and @dflag = 0
BEGIN
     SET @activity = 'Добавление';

     INSERT INTO [dbo].[Audit_operations] ([Вид операции],[Время операции]) VALUES (@activity, @dateNow);
     SET @idVid = SCOPE_IDENTITY();
     
     INSERT INTO [dbo].[Audit_sort_project] ([Номер операции], [Шифр сотрудника], [Старый шифр проекта], [Новый шифр проекта])
       SELECT 
             @idVid,
             [code_employer],
             111,
             111
       FROM INSERTED;
END
ELSE IF @dflag = 1 AND @iflag = 0
BEGIN
     SET @activity = 'Удаление';

     INSERT INTO [dbo].[Audit_operations] ([Вид операции],[Время операции]) VALUES (@activity, @dateNow);
END;


...
Рейтинг: 0 / 0
30.04.2020, 13:43
    #39953270
iap
iap
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Консультация по тригерам.
felix_ff
Триггер должен выглядеть как то так:
Не согласен.
Я бы добавил:

1. Выбросьте из триггера все скалярные переменные.
2. Работайте с deleted и inserted как с таблицами.
...
Рейтинг: 0 / 0
30.04.2020, 15:17
    #39953310
iap
iap
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Консультация по тригерам.
iap
felix_ff
Триггер должен выглядеть как то так:
Не согласен.
Я бы добавил:

1. Выбросьте из триггера все скалярные переменные.
2. Работайте с deleted и inserted как с таблицами.
3. Если на DELETE, INSERT и UPDATE разная обработка,
то и напишите 3 триггера вместо одного. Зачем корячиться-то?
...
Рейтинг: 0 / 0
30.04.2020, 15:52
    #39953316
alexeyvg
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Консультация по тригерам.
felix_ff
У Вас проблема вот тут:
Код: sql
1.
Select @idVid = (Select scope_identity() from Audit_operations)


на момент второго срабатывания в триггере записей в Audit_operations будет больше 1, соответственно присваивание множественных значений переменной не допустимо.
Как я понял, в Audit_operations должна быть одна запись на любое количество обрабатываемых строк в sotr_project
Так что сойдёт...

iap
felix_ff
Триггер должен выглядеть как то так:
Не согласен.
Я бы добавил:

1. Выбросьте из триггера все скалярные переменные.
2. Работайте с deleted и inserted как с таблицами.
Вы заметили, что он хочет логировать изменение ПК? :-)
...
Рейтинг: 0 / 0
01.05.2020, 07:42
    #39953472
Frankestein
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Консультация по тригерам.
felix_ff,

Спасибо большое за подробное разъяснение моих ошибок.
...
Рейтинг: 0 / 0
01.05.2020, 07:43
    #39953473
Frankestein
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Консультация по тригерам.
Всем большое спасибо за помощь и консультацию.
...
Рейтинг: 0 / 0
Форумы / Microsoft SQL Server [игнор отключен] [закрыт для гостей] / Консультация по тригерам. / 7 сообщений из 7, страница 1 из 1
Целевая тема:
Создать новую тему:
Автор:
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


Просмотр
0 / 0
Close
Debug Console [Select Text]