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

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

16.11.2022, 13:43. Показов 2857. Ответов 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
885 / 148 / 35
Регистрация: 05.08.2022
Сообщений: 681
17.11.2022, 15:37  [ТС]
Студворк — интернет-сервис помощи студентам
Цитата Сообщение от PaulWist Посмотреть сообщение
получение "нового номера
SQL
1
 ID INT IDENTITY(1,1) NOT NULL,
обычная история, все базы на ней построены, разве нет?

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

2. Да, обычно для лога берут PK обновляемой таблицы.
0
 Аватар для alecko5
885 / 148 / 35
Регистрация: 05.08.2022
Сообщений: 681
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
672 / 295 / 121
Регистрация: 12.04.2022
Сообщений: 1,008
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
885 / 148 / 35
Регистрация: 05.08.2022
Сообщений: 681
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
885 / 148 / 35
Регистрация: 05.08.2022
Сообщений: 681
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
885 / 148 / 35
Регистрация: 05.08.2022
Сообщений: 681
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
885 / 148 / 35
Регистрация: 05.08.2022
Сообщений: 681
18.11.2022, 22:43  [ТС]
Цитата Сообщение от Аватар Посмотреть сообщение
и чего не мешает запихнуть в tblLOGDanns
не мешает, но в tblLOGDanns большие стринги(varchar(max)) , а в tblLOGcover - int и date (в дальнейшей обработке все очень неплохо разделяется и работает)
но как увидели, даже если запихну, как ключ получу? identity(1,1) использовать нельзя.
насчет курсоров в триггере согласен на все 146%, но лучше ничего не увидел, а так - по скорости юзабельно.
0
 Аватар для alecko5
885 / 148 / 35
Регистрация: 05.08.2022
Сообщений: 681
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
885 / 148 / 35
Регистрация: 05.08.2022
Сообщений: 681
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
Ответ Создать тему
Новые блоги и статьи
Генератор паролей (вариант №4)
Maks 01.11.2026
После публикации 3-го варианта генератора паролей, разослал его своим коллегам (с целью оценки), в итоге были получены следующие рекомендации: 1. Вернуть возможность использования знаков | 1 l I;. . .
Генератор паролей (вариант №3)
Maks 30.10.2026
Финальная версия генератора паролей 1С. Доработка решения в этот раз коснулась только визуальной части, а именно, добавлен реквизит ДопПараметры (тип Булево), который скрывает/ отображает реквизиты:. . .
Магическое мышление и магия, современная наука не отличима от магии (говорит ИИ Джемени)
zorxor 30.10.2026
Джемени, расскажи, пожалуйста, что такое магическое мышление, что такое магия, почему современная наука чем-то напоминает магию? Фраза «Любая достаточно развитая технология неотличима от магии». . .
За какое время ИИ может подобрать пароль по хешу (рассказывает Джемени ИИ)
zorxor 30.10.2026
Расскажи, Джемени, если известен хэш МД5, например, за сколько ИИ сможет подобрать соответствующий пароль? Искусственный интеллект (ИИ) может подобрать простой или средний по сложности пароль по. . .
Кто убил Suno? Почему наше солнышко погасло? (диалог с ИИ Джемени)
zorxor 30.10.2026
Как убивали Suno. Хронология. «Убийство» музыкальной нейросети Suno — это затяжной процесс, в котором технологический хайп стартапа разбился о жесткую реальность судебных исков от гигантов. . .
Генератор паролей (вариант №2)
Maks 30.10.2026
Обновленная версия ранее созданной обработки. Добавлены следующие реквизиты типа Булево: - Буквы; - Цифры; - Символы. Изменена логика команды "Сгенерировать" и процедуры "ПриОткрытии":. . .
Генератор паролей (вариант №1)
Maks 29.10.2026
Реализация из решения ниже выполнена исключительно по моей инициативе, дабы облегчить себе работу в создании паролей для администрируемых мною сервисов и пользователей. Самым главным критерием для. . .
Установка ChatGPT (Codex) на Windows без использования Microsoft Store
Fabien159 28.10.2026
Здравствуйте всем читающим! Опишу процесс установки ChatGPT (Codex) на Windows, если по каким-то причинам у вас не получается устанавить его через Microsoft Store. И так: 1. Скачиваем с. . .
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2026, CyberForum.ru