Форум программистов, компьютерный форум, киберфорум
Microsoft SQL Server
Войти
Регистрация
Восстановить пароль
Блоги Сообщество Поиск Заказать работу  
 
 
Рейтинг 4.89/9: Рейтинг темы: голосов - 9, средняя оценка - 4.89
 Аватар для alecko5
884 / 147 / 35
Регистрация: 05.08.2022
Сообщений: 680

Триггер блокирует таблицу

16.11.2022, 13:43. Показов 2637. Ответов 33

Студворк — интернет-сервис помощи студентам
Триггеры журналирования, с таблицей его работа не связана, добавляет действия в пару таблиц, отрабатывает, но... в блокирует таблицу, как будто это INSTEAD OF
вот пример.
Кликните здесь для просмотра всего текста
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
CREATE TRIGGER [dbo].[tmpProduct_Insert] 
   ON   [dbo].[tmpProduct]
  AFTER  INSERT
AS 
BEGIN
SET nocount ON
DECLARE @Naimtable VARCHAR(55)= 'tmpProduct';
DECLARE @k2 INT=960--название таблицы понятное для пользователя
DECLARE @k1 INT=201 --добавление
DECLARE  @k0  INT, @IDT INT, @strNEW nvarchar(MAX),  @str2 nvarchar(25), @t1 nvarchar(25);
SELECT @k0 =IDN FROM tblIN WHERE (IDU=SUSER_ID (sUSER_NAME()));
DECLARE C cursor fast_forward FOR
 SELECT id FROM inserted;
 OPEN c
fetch  c INTO @t1
while (@@FETCH_STATUS =0)
BEGIN
INSERT INTO tblLOGcover (idu,idAction,idzmen, NameTabl) VALUES(@k0,@k1,@k2, @Naimtable );--занесли в таблицу с метаданными
SET @IDT=@@IDENTITY 
SELECT @strNEW=(CAST([ID] AS  nvarchar(15)) + '|' + CAST([iSmena] AS  nvarchar(55)) + '|' + CAST([idM] AS  nvarchar(55)) + '|' + CAST([Nomer] AS  nvarchar(55)) + '|' + CAST([daGood] AS  nvarchar(55))) FROM inserted  WHERE ([id]=@t1);
INSERT INTO tblLOGDanns (idC, FRESH) VALUES(@IDT, @strNEW  );
fetch NEXT FROM c INTO @t1
END
 
close c;
deallocate c;
END
 
GO

Повторюсь в таблицы tblLOGcover,tblLOGDanns все записывается, но таблица tmpProduct блокируется. С чего бы?
0
IT_Exp
Эксперт
34794 / 4073 / 2104
Регистрация: 17.06.2006
Сообщений: 32,602
Блог
16.11.2022, 13:43
Ответы с готовыми решениями:

Не срабатывает триггер после вставки внутри триггера в таблицу, для которой реализован триггер
Добрый день. Есть таблица A. Для таблицы A сделан триггер A_T, срабатывающий AFTER INSERT в таблицу A. Внутри триггера A_T может...

Разработать триггер, запускаемый при занесении новой строки в таблицу. Триггер должен увеличивать счетчик ч
Разработать триггер, запускаемый при занесении новой строки в таблицу. Триггер должен увеличивать счетчик числа добавленных строк.

Триггер, добавляющий строку в таблицу
Доброго времени суток! Нужно реализовать триггер, который по событию after update добавляет обновленные данные в определённую таблицу....

33
 Аватар для alecko5
884 / 147 / 35
Регистрация: 05.08.2022
Сообщений: 680
17.11.2022, 15:37  [ТС]
Студворк — интернет-сервис помощи студентам
Цитата Сообщение от PaulWist Посмотреть сообщение
получение "нового номера
SQL
1
 ID INT IDENTITY(1,1) NOT NULL,
обычная история, все базы на ней построены, разве нет?

Добавлено через 14 минут
получается нужно отказаться от автоинкремента в tblLOGcover,tblLOGDanns, создавать в них просто коды или CREATE SEQUENCE , да вообще из инсерта брать ключ.
0
671 / 294 / 120
Регистрация: 12.04.2022
Сообщений: 1,003
18.11.2022, 09:32
Цитата Сообщение от alecko5 Посмотреть сообщение
получается нужно отказаться от автоинкремента в tblLOGcover,tblLOGDanns, создавать в них просто коды или CREATE SEQUENCE , да вообще из инсерта брать ключ.
1. Нет, от автоинкримента можно не отказываться, достаточно - правильно использовать системные ф-ии (о чём дважды уже писал)

2. Да, обычно для лога берут PK обновляемой таблицы.
0
 Аватар для alecko5
884 / 147 / 35
Регистрация: 05.08.2022
Сообщений: 680
18.11.2022, 11:25  [ТС]
Цитата Сообщение от PaulWist Посмотреть сообщение
автоинкримента можно не отказываться, достаточно - правильно использовать системные ф-ии (о чём дважды уже писал)
именно в автоинкременте и происходит подмена номера - сюда он вставляется
SQL
1
 ID INT IDENTITY(1,1) NOT NULL,
из в @@identity, которая содержит номер , сгенерированный счетчиком при вставке в стороннюю таблицу.

Добавлено через 2 минуты
Цитата Сообщение от PaulWist Посмотреть сообщение
Да, обычно для лога берут PK обновляемой таблицы
неа - ключ должен быть уникальным, а у нас не только INSERT, но еще и UPDATE, DELETE еще пара других триггеров, приходится генерировать вручную-тиа такого, глвное чтоб в @@identity ничего не писалось.
SQL
1
SELECT @idG=MAX(ID) FROM dbo.tblLOGcover
0
671 / 294 / 120
Регистрация: 12.04.2022
Сообщений: 1,003
18.11.2022, 13:31
Блин.

1. Это путь в никуда.

T-SQL
1
SELECT @idG=MAX(ID) FROM dbo.tblLOGcover
2. Получить "последнее" вставленное/сгенерированное значение поля identity надо так:

T-SQL
1
2
3
insert into MyMasterTable values (.....)
set @id = scope_identity()
-- дальше уже можно использовать @id для таблиц Детали
Замени @@identity на scope_identity()
0
 Аватар для alecko5
884 / 147 / 35
Регистрация: 05.08.2022
Сообщений: 680
18.11.2022, 16:21  [ТС]
Цитата Сообщение от PaulWist Посмотреть сообщение
Замени @@identity на scope_identity()
я их вообще не использую.
вот кусок триггера
Кликните здесь для просмотра всего текста
SQL
1
2
3
4
5
6
7
8
9
10
11
DECLARE C cursor fast_forward FOR
SELECT (CAST([ID] AS  nvarchar(15)) + '|' + CAST(isnull([vid],'') AS  nvarchar(55)) + '|' + CAST(isnull([ida],'') AS  nvarchar(55)) + '|' + CAST(isnull([Nomr],'') AS  nvarchar(55)) + '|' + CAST(isnull([Kogda],'') AS  nvarchar(55)) + '|' + CAST(isnull([CostPrihod],'') AS  nvarchar(55)) + '|' + CAST(isnull([Prihod],'') AS  nvarchar(55))) FROM inserted;
 OPEN c
fetch  c INTO @strNEW
while (@@FETCH_STATUS =0) BEGIN
SET @idG=@idG+1
INSERT INTO tblLOGcover (id, idu,idAction,idzmen, NameTabl) VALUES(@idg, @k0,@k1,@k2, @Naimtable  );--занесли в таблицу с метаданными
INSERT INTO tblLOGDanns (idC, FRESH) VALUES(@idg, @strNEW  );
fetch NEXT FROM c INTO @strNEW
END
close c;

а @@identity использует сервер, в автоинкременте ключа ID identity (1,1)

Добавлено через 3 минуты
напоминаю триггер на вставку новой строки в tmpProduct - другая таблица.

Добавлено через 17 минут
а подмена числа ключа ID происходит, потому что @@identity заменяется сработавшими автоинкрементами при вставке в таблицы tblLOGcover, tblLOGDanns - в триггере.
Поэтому в этих таблицах отказался от автоинкремента.
0
 Аватар для Аватар
5393 / 1465 / 513
Регистрация: 31.05.2012
Сообщений: 5,153
18.11.2022, 17:51
а зачем вообще курсор? вот логирование в обну из таблиц, в другую аналогично.
SQL
1
2
INSERT INTO tblLOGDanns (idC, FRESH)
  SELECT id, CAST([ID] AS  nvarchar(15) + ... +CAST([daGood] AS  nvarchar(55)) FROM inserted
0
 Аватар для alecko5
884 / 147 / 35
Регистрация: 05.08.2022
Сообщений: 680
18.11.2022, 19:07  [ТС]
Цитата Сообщение от Аватар Посмотреть сообщение
а зачем вообще курсор?
записей может быть много, idc не из инсертед-она берется из id tblLOGcover.
Хотя по факту раз получили, потом просто изменяется на 1 и записывается в качестве первичного в tblLOGcover и внешнего в tblLOGDanns
0
 Аватар для Аватар
5393 / 1465 / 513
Регистрация: 31.05.2012
Сообщений: 5,153
18.11.2022, 21:10
Цитата Сообщение от alecko5 Посмотреть сообщение
idc не из инсертед-она берется из id tblLOGcover
ну это ты нафантазировал. в лог должна писаться ссылка на логируемую таблицу, иначе зачем он
0
 Аватар для alecko5
884 / 147 / 35
Регистрация: 05.08.2022
Сообщений: 680
18.11.2022, 22:19  [ТС]
[tblLOGDanns] связана таблицей с tblLOGcover
SQL
1
2
3
4
ALTER TABLE [dbo].[tblLOGDanns]  WITH CHECK ADD  CONSTRAINT [fk_tblLOGDanns] FOREIGN KEY([idC])
REFERENCES [dbo].[tblLOGcover] ([ID])
ON DELETE CASCADE
GO
0
 Аватар для Аватар
5393 / 1465 / 513
Регистрация: 31.05.2012
Сообщений: 5,153
18.11.2022, 22:29
Лучший ответ Сообщение было отмечено alecko5 как решение

Решение

а смысл этого? в tblLOGcover пишешь ид на каждую вставляемую запись, а tblLOGDanns связываешь с ключем этой таблицы зачем то, зачем она вообще нужна эта tblLOGcover? все то что в нее запихнул ни чего не мешает запихнуть в tblLOGDanns. и вообще - курсоры придуманы не для использования в триггерах, очень плохой тон работы с базой
0
 Аватар для alecko5
884 / 147 / 35
Регистрация: 05.08.2022
Сообщений: 680
18.11.2022, 22:43  [ТС]
Цитата Сообщение от Аватар Посмотреть сообщение
и чего не мешает запихнуть в tblLOGDanns
не мешает, но в tblLOGDanns большие стринги(varchar(max)) , а в tblLOGcover - int и date (в дальнейшей обработке все очень неплохо разделяется и работает)
но как увидели, даже если запихну, как ключ получу? identity(1,1) использовать нельзя.
насчет курсоров в триггере согласен на все 146%, но лучше ничего не увидел, а так - по скорости юзабельно.
0
 Аватар для alecko5
884 / 147 / 35
Регистрация: 05.08.2022
Сообщений: 680
19.11.2022, 13:47  [ТС]
Вынужден согласится, оставил одну таблицу [tblLOGcover],
сваял такую функцию
Кликните здесь для просмотра всего текста
SQL
1
2
3
4
5
6
7
8
9
10
CREATE FUNCTION [dbo].[SQLSequence]() 
RETURNS INT
AS
-- place the body of the function here
BEGIN
DECLARE @i INT, @Res INT
SELECT @i=MAX(ID) FROM dbo.tblLOGcover
    SET @Res = @i+1
     RETURN @Res
END

заодно уж чтоб 2 раза не вставать, скрипт создающий по 3 триггера на таблицу.
Кликните здесь для просмотра всего текста
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
54
55
56
57
58
59
60
USE [DannTablesAccess]
GO
DECLARE @Naimtable VARCHAR(55)= 'tmpProduct';
DECLARE @k2 VARCHAR(5)=960' это как раз ссылка на таблицу в мерках клиента
declare @O0b varchar(180)='GO
ALTER TRIGGER [dbo].[' + @Naimtable + '_'
 
declare @O1b varchar(180)='] 
   ON   [dbo].[' + @Naimtable + ']
  AFTER  '
declare @Ob varchar(180)='
AS
BEGIN
SET nocount ON
DECLARE @Naimtable VARCHAR(55)= ''' + @Naimtable + '''; 
DECLARE @k2 INT=' + @k2 + '
 DECLARE @k1 INT='
declare @ob1 varchar(100)='
DECLARE  @k0  INT;
SELECT @k0 =IDN FROM tblIN WHERE (IDU=SUSER_ID (SUSER_NAME()));'
 
declare  @k0  int, @IDT int,@strcolumns nvarchar(max),@strcolumns2 nvarchar(max)
,@str2 nvarchar(25);
declare @t1 int,   @t10 as nvarchar(25);
 
--begin try
declare C cursor fast_forward for
select name from sys.columns where object_id = OBJECT_ID(@Naimtable);
 open c
fetch  c into @str2
set @strcolumns= 'CAST([inserted].[' + @str2 +'] AS  nvarchar(15))'
set @strcolumns2= 'CAST([deleted].[' + @str2 +'] AS  nvarchar(15))'
 
fetch next from c into @str2
while (@@FETCH_STATUS =0)
begin
set @strcolumns=@strcolumns + ' + ''|'' + CAST(isnull([inserted].[' +@str2+ '],'''') AS  nvarchar(55))'
set @strcolumns2=@strcolumns2 + ' + ''|'' + CAST(isnull([deleted].[' +@str2+ '],'''') AS  nvarchar(55))'
 
fetch next from c into @str2
end
print @O0b + 'INSERT' + @O1b + 'INSERT' +
@Ob + '201' + @ob1 + ' 
INSERT INTO tblLOGcover (id, idu,idAction,idzmen, NameTabl,FRESH)
SELECT dbo.SQLSequence() AS d1,  @k0 AS d2,@k1 AS d3,@k2 AS d4, @Naimtable AS d5,' + @strcolumns + ' AS ki FROM inserted;
END'
print @O0b + 'DELETE' + @O1b + 'DELETE' +
@Ob + '202' + @ob1 + '
INSERT INTO tblLOGcover (id, idu,idAction,idzmen, NameTabl, OLD )
SELECT dbo.SQLSequence() AS d1,  @k0 AS d2,@k1 AS d3,@k2 AS d4, @Naimtable AS d5,' + @strcolumns2 + ' AS kd FROM deleted;
END'
 
print @O0b + 'UPDATE' + @O1b + 'UPDATE' +
@Ob + '203' + @ob1 + '
INSERT INTO tblLOGcover (id, idu,idAction,idzmen, NameTabl,OLD, FRESH)
SELECT dbo.SQLSequence() AS d1,  @k0 AS d2,@k1 AS d3,@k2 AS d4, @Naimtable AS d5
,' + @strcolumns2 + ' AS kd
,' + @strcolumns + ' AS ki FROM inserted INNER JOIN deleted ON inserted.id=deleted.id;
END
GO'
close c;
deallocate c;
go

получаем триггеры такого вида
Кликните здесь для просмотра всего текста
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
GO
ALTER TRIGGER [dbo].[tmpProduct_Insert] 
   ON   [dbo].[tmpProduct]
  AFTER  INSERT
AS
BEGIN
SET nocount ON
DECLARE @Naimtable VARCHAR(55)= 'tmpProduct'; 
DECLARE @k2 INT=960
 DECLARE @k1 INT=201
DECLARE  @k0  INT;
SELECT @k0 =IDN FROM tblIN WHERE (IDU=SUSER_ID (SUSER_NAME())); 
INSERT INTO tblLOGcover (id, idu,idAction,idzmen, NameTabl,FRESH)
SELECT dbo.SQLSequence() AS d1,  @k0 AS d2,@k1 AS d3,@k2 AS d4, @Naimtable AS d5,CAST([inserted].[ID] AS  nvarchar(15)) + '|' + CAST(isnull([inserted].[iSmena],'') AS  nvarchar(55)) + '|' + CAST(isnull([inserted].[idM],'') AS  nvarchar(55)) + '|' + CAST(isnull([inserted].[Nomer],'') AS  nvarchar(55)) + '|' + CAST(isnull([inserted].[daGood],'') AS  nvarchar(55)) AS ki FROM inserted;
END
GO
ALTER TRIGGER [dbo].[tmpProduct_Delete] 
   ON   [dbo].[tmpProduct]
  AFTER  DELETE
AS
BEGIN
SET nocount ON
DECLARE @Naimtable VARCHAR(55)= 'tmpProduct'; 
DECLARE @k2 INT=960
 DECLARE @k1 INT=202
DECLARE  @k0  INT;
SELECT @k0 =IDN FROM tblIN WHERE (IDU=SUSER_ID (SUSER_NAME()));
INSERT INTO tblLOGcover (id, idu,idAction,idzmen, NameTabl, OLD )
SELECT dbo.SQLSequence() AS d1,  @k0 AS d2,@k1 AS d3,@k2 AS d4, @Naimtable AS d5,CAST([deleted].[ID] AS  nvarchar(15)) + '|' + CAST(isnull([deleted].[iSmena],'') AS  nvarchar(55)) + '|' + CAST(isnull([deleted].[idM],'') AS  nvarchar(55)) + '|' + CAST(isnull([deleted].[Nomer],'') AS  nvarchar(55)) + '|' + CAST(isnull([deleted].[daGood],'') AS  nvarchar(55)) AS kd FROM deleted;
END
GO
ALTER TRIGGER [dbo].[tmpProduct_Update] 
   ON   [dbo].[tmpProduct]
  AFTER  UPDATE
AS
BEGIN
SET nocount ON
DECLARE @Naimtable VARCHAR(55)= 'tmpProduct'; 
DECLARE @k2 INT=960
 DECLARE @k1 INT=203
DECLARE  @k0  INT;
SELECT @k0 =IDN FROM tblIN WHERE (IDU=SUSER_ID (SUSER_NAME()));
INSERT INTO tblLOGcover (id, idu,idAction,idzmen, NameTabl,OLD, FRESH)
SELECT dbo.SQLSequence() AS d1,  @k0 AS d2,@k1 AS d3,@k2 AS d4, @Naimtable AS d5
,CAST([deleted].[ID] AS  nvarchar(15)) + '|' + CAST(isnull([deleted].[iSmena],'') AS  nvarchar(55)) + '|' + CAST(isnull([deleted].[idM],'') AS  nvarchar(55)) + '|' + CAST(isnull([deleted].[Nomer],'') AS  nvarchar(55)) + '|' + CAST(isnull([deleted].[daGood],'') AS  nvarchar(55)) AS kd
,CAST([inserted].[ID] AS  nvarchar(15)) + '|' + CAST(isnull([inserted].[iSmena],'') AS  nvarchar(55)) + '|' + CAST(isnull([inserted].[idM],'') AS  nvarchar(55)) + '|' + CAST(isnull([inserted].[Nomer],'') AS  nvarchar(55)) + '|' + CAST(isnull([inserted].[daGood],'') AS  nvarchar(55)) AS ki FROM inserted INNER JOIN deleted ON inserted.id=deleted.id;
END
GO
0
3614 / 2135 / 756
Регистрация: 02.06.2013
Сообщений: 5,169
19.11.2022, 20:32
Цитата Сообщение от alecko5 Посмотреть сообщение
сваял такую функцию
Количество строителей велосипедов с квадратными колесами для лазания по деревьям никогда не убывает...

1. Что вернет эта чудо-функция, когда dbo.tblLOGcover пустая?
2. Чем гарантриуется, что при конкурентном выполнении вернутся разные значения?

Чем ваять велосипеды, почитайте про sequence
1
 Аватар для alecko5
884 / 147 / 35
Регистрация: 05.08.2022
Сообщений: 680
19.11.2022, 21:33  [ТС]
Цитата Сообщение от invm Посмотреть сообщение
почитайте про sequence
в 2008 сервере такой функции нет.
Цитата Сообщение от invm Посмотреть сообщение
когда dbo.tblLOGcover пустая
пустой не будет, но за наводку спасибо.
Цитата Сообщение от invm Посмотреть сообщение
Чем гарантриуется, что при конкурентном выполнении вернутся разные значения?
плавно подтягивается GUID...
0
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
BasicMan
Эксперт
29316 / 5623 / 2384
Регистрация: 17.02.2009
Сообщений: 30,364
Блог
19.11.2022, 21:33
Помогаю со студенческими работами здесь

Триггер для ограничения ввода записей в таблицу
Здравствуйте! Делаю базу данных больница, в ней есть таблица Лечение (Lechenie),куда я добавляю пациента и всю информацию о его...

Триггер на перенос/копирование данных в другую таблицу
Добрый день. Есть таблица с документами. В ней есть столбец с датой исполнения (dat_isp) и отметка об исполнении (otm_isp). ...

Создать триггер, который записывает в таблицу время внесения изменения...
Создать триггер, который записывает в таблицу tblCustomLog информацию про время внесения изменения (ChangeTime), пользователе под которым...

Триггер: изменение числа в одной таблице при INSERT данных в другую таблицу
Здравствуйте. Вопрос по созданию триггера. У меня есть 2 таблицы: Students (Sno char(3), Sname char(8), Count int) и Score(Sno char(3),...

SELECT блокирует таблицу
При запросе данных из таблицы, остальные пользователи становятся в очередь (waiting for table level lock). Как правильно делать...


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
34
Ответ Создать тему
Новые блоги и статьи
Благородство как наказание
Maks 24.04.2026
У хорошего человека отношения с женщинами всегда складываются трудно. А я человек хороший. Заявляю без тени смущения, потому что гордиться тут нечем. От хорошего человека ждут соответствующего. . .
Валидация и контроль данных табличной части документа перед записью
Maks 22.04.2026
Алгоритм из решения ниже реализован на примере нетипового документа, разработанного в КА2. Задача: контроль и валидация данных табличной части документа перед записью с учетом регламента компании. . .
Отчёт о затраченных материалах за определенный период с макетом печатной формы
Maks 21.04.2026
Отчёт из решения ниже размещён в конфигурации КА2. Задача: разработка отчёта по затраченным материалам за определённый период, с возможностью вывода печатной формы отчёта с шапкой и подвалом. В. . .
Отчёт о спецтехнике находящейся в ремонте
Maks 20.04.2026
Отчёт из решения ниже размещен в конфигурации КА2. Задача: отобразить спецтехнику, которая на данный момент находится в ремонте. Есть нетиповой документ "Заявка на ремонт спецтехники" который. . .
Памятка для бота и "визитка" для читателей "Semantic Universe Layer (Слой семантической вселенной)"
Hrethgir 19.04.2026
Сгенерировано для краткого описания по случаю сборки и компиляции скелета серверного приложения. И пусть после этого скажут, что статьи сгенерированные AI - туфта и не интересно. И это не реклама -. . .
Запрет удаления строк ТЧ документа при определённом условии
Maks 19.04.2026
Алгоритм из решения ниже реализован на примере нетипового документа "Аккумуляторы", разработанного в конфигурации КА2. У данного документа есть ТЧ, в которой в зависимости от прав доступа. . .
Модель заражения группы наркоманов
alhaos 17.04.2026
Условия задачи сформулированы тут Суть: - Группа наркоманов из 10 человек. - Только один инфицирован ВИЧ. - Колются одной иглой. - Колются раз в день. - Колются последовательно через. . .
Мысли в слух. Про "навсегда".
kumehtar 16.04.2026
Подумалось тут, что наверное очень глупо использовать во всяких своих установках понятие "навсегда". Это очень сильное понятие, и я только начинаю понимать край его смысла, не смотря на то что давно. . .
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2026, CyberForum.ru