powered by simpleCommunicator - 2.0.53     © 2025 Programmizd 02
Форумы / Microsoft SQL Server [игнор отключен] [закрыт для гостей] / Консультация по тригерам.
7 сообщений из 7, страница 1 из 1
Консультация по тригерам.
    #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
Консультация по тригерам.
    #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
Консультация по тригерам.
    #39953270
iap
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
felix_ff
Триггер должен выглядеть как то так:
Не согласен.
Я бы добавил:

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

1. Выбросьте из триггера все скалярные переменные.
2. Работайте с deleted и inserted как с таблицами.
3. Если на DELETE, INSERT и UPDATE разная обработка,
то и напишите 3 триггера вместо одного. Зачем корячиться-то?
...
Рейтинг: 0 / 0
Консультация по тригерам.
    #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
Консультация по тригерам.
    #39953472
Frankestein
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
felix_ff,

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


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