Добро пожаловать в форум, Guest  >>   Войти | Регистрация | Поиск | Правила | В избранное | Подписаться
Все форумы / Microsoft SQL Server Новый топик    Ответить
 MS SQL: как красиво сделать триггер для автоматической вставки части первичного ключа  [new]
afend
Member

Откуда:
Сообщений: 133
Мастера жанра, помогите!

Есть табличка типа этой:

id_1id_2Title

2341AAAA

2342BBBB

2343CCCC

4561DDDD

4562EEEE

4563FFFF


id_1 и id_2 - ключи.
id_1 вставляется при insert (пардон за тавтологию).
А id_2 должна вставляться триггером как максимальное
существующее в таблице значение id_2 для соответствующего id_1, плюс 1.

Заранее благодарен!

Сообщение было отредактировано: 19 окт 14, 21:09
19 окт 14, 19:19    [16728100]     Ответить | Цитировать Сообщить модератору
 Re: MS SQL: как красиво сделать триггер для автоматической вставки части первичного ключа  [new]
pkarklin
Member

Откуда: Москва (Муром)
Сообщений: 74925
Что изменится, если данные будут выглядеть так:

id_1id_2Title

234101AAAA

234113BBBB

234147CCCC

456151DDDD

456240EEEE

456315FFFF


?

Сообщение было отредактировано: 19 окт 14, 22:23
19 окт 14, 21:14    [16728364]     Ответить | Цитировать Сообщить модератору
 Re: MS SQL: как красиво сделать триггер для автоматической вставки части первичного ключа  [new]
afend
Member

Откуда:
Сообщений: 133
pkarklin,

ну, вообще-то там последовательные цифры...
А в чём особенность такого расклада?
19 окт 14, 22:35    [16728637]     Ответить | Цитировать Сообщить модератору
 Re: MS SQL: как красиво сделать триггер для автоматической вставки части первичного ключа  [new]
afend
Member

Откуда:
Сообщений: 133
После курения мануалов мой вариант на критику:

CREATE TRIGGER myTriggerName ON testTable
instead OF INSERT AS
BEGIN
DECLARE @id_1_Value INT
DECLARE @id_2_Value INT
SET @id_1_Value=(SELECT id_1 FROM inserted)
SET @id_2_Value=(SELECT MAX(id_2) FROM testTable T1 WHERE T1.SiteId = @id_1_Value)
IF(@id_2_Value IS null) SET @id_2_Value=0
INSERT INTO testTable (id_1, Title)
SELECT inserted.id_1, (@id_2_Value+1), inserted.Title
FROM inserted
END

Вроде, работает. Чё здесь плохого?...
20 окт 14, 09:40    [16729342]     Ответить | Цитировать Сообщить модератору
 Re: MS SQL: как красиво сделать триггер для автоматической вставки части первичного ключа  [new]
afend
Member

Откуда:
Сообщений: 133
afend
После курения мануалов мой вариант на критику:

CREATE TRIGGER myTriggerName ON testTable
instead OF INSERT AS
BEGIN
DECLARE @id_1_Value INT
DECLARE @id_2_Value INT
SET @id_1_Value=(SELECT id_1 FROM inserted)
SET @id_2_Value=(SELECT MAX(id_2) FROM testTable T1 WHERE T1.SiteId = @id_1_Value)
IF(@id_2_Value IS null) SET @id_2_Value=0
INSERT INTO testTable (id_1, Title)
SELECT inserted.id_1, (@id_2_Value+1), inserted.Title
FROM inserted
END

Вроде, работает. Чё здесь плохого?...


Сорри, кое-что забыл правильно проапдейтить. Теперь:

CREATE TRIGGER myTriggerName ON testTable
instead OF INSERT AS
BEGIN
DECLARE @id_1_Value INT
DECLARE @id_2_Value INT
SET @id_1_Value=(SELECT id_1 FROM inserted)
SET @id_2_Value=(SELECT MAX(id_2) FROM testTable T1 WHERE T1.id_1 = @id_1_Value)
IF(@id_2_Value IS null) SET @id_2_Value=0
INSERT INTO testTable (id_1, Title)
SELECT inserted.id_1, (@id_2_Value+1), inserted.Title
FROM inserted
END
20 окт 14, 09:42    [16729359]     Ответить | Цитировать Сообщить модератору
 Re: MS SQL: как красиво сделать триггер для автоматической вставки части первичного ключа  [new]
stdvb
Member

Откуда:
Сообщений: 38
afend
Чё здесь плохого?...

Плохо то, что inserted это таблица, а не одна строка.
20 окт 14, 09:46    [16729387]     Ответить | Цитировать Сообщить модератору
 Re: MS SQL: как красиво сделать триггер для автоматической вставки части первичного ключа  [new]
invm
Member

Откуда: Москва
Сообщений: 9406
afend
Чё здесь плохого?...
Плохо все.
1. В inserted может быть более одной строки.
2. На TIL младше SERIALIZABLE будете получать дубликаты ключей.

Лучше объясните для чего нужна последовательная нумерация.
20 окт 14, 09:59    [16729447]     Ответить | Цитировать Сообщить модератору
 Re: MS SQL: как красиво сделать триггер для автоматической вставки части первичного ключа  [new]
Crimean
Member

Откуда:
Сообщений: 13148
еще и конкурентные вставки убъете :)
20 окт 14, 10:14    [16729541]     Ответить | Цитировать Сообщить модератору
 Re: MS SQL: как красиво сделать триггер для автоматической вставки части первичного ключа  [new]
pkarklin
Member

Откуда: Москва (Муром)
Сообщений: 74925
afend
ну, вообще-то там последовательные цифры...


А они действительно нужны последовательные?

afend
А в чём особенность такого расклада?


Его можно реализовать без триггера.
20 окт 14, 11:23    [16729901]     Ответить | Цитировать Сообщить модератору
 Re: MS SQL: как красиво сделать триггер для автоматической вставки части первичного ключа  [new]
Jaffar
Member

Откуда:
Сообщений: 633
T,fnm ns kj[!!!
Прошу прощения


по сути:
В таблице не хватает уникального ключа, для случая вставки нескольких строчек с одинаковым значением ID1 и NULL`ом в ID2.
В oracle ЭТО называется rowID.

поэтому если добавить еще 1 стб. то получится вот так:

create table tmp_LEX(
ID1 int not NULL,
ID2 int NULL,
Title varchar(255) not NULL,
ID_XX int identity(1, 1) )



select * from tmp_Lex order by ID1, ID2
insert tmp_Lex(ID1, ID2, Title)
select 710, NULL, 'ff'
union all
select 256, 17, 'ff'
union all
select 420, 1, 'ff'
union all
select 420, 2, 'ff'
union all
select 256, 3, 'ff'
union all
select 256, 32, 'ff' -- новые записи
union all
select 256, NULL, 'ff'
union all
select 420, NULL, 'ff'
union all
select 420, NULL, 'ff'
union all
select 256, NULL, 'ff'


select i.*,  isNULL(t.max_prev, 0) Max_Prev, row_number() over(partition by i.ID1 order by i.ID1, i.Title asc) NN
from (select * from tmp_lex  with(nolock) where ID2 is NULL) i
left join (select t.ID1, max(t.ID2) max_Prev from tmp_lex t with(nolock) group by t.ID1/**/) t on t.ID1 = i.ID1




create trigger ti_tmp_LEX on tmp_LEX
for insert
as
begin

update t
set
		t.ID2 = tn.ID2
from tmp_Lex t
join (select i.ID_XX, IsNULL(t.Max_Prev, 0) + row_number() over(partition by i.ID1 order by i.ID1 asc, i.Title asc) ID2
	  from inserted i
	  left join (select t.ID1, max(t.ID2) Max_Prev from tmp_Lex t with(nolock) group by t.ID1 /**/) t on t.ID1 = i.ID1
	  where
				i.ID2 is NULL /**/ ) tn on t.ID_XX = tn.ID_XX
end;
20 окт 14, 13:06    [16730612]     Ответить | Цитировать Сообщить модератору
 Re: MS SQL: как красиво сделать триггер для автоматической вставки части первичного ключа  [new]
afend
Member

Откуда:
Сообщений: 133
invm,

это унаследованное приложение с БД, поэтому менять
структуру череповато. Что касается массовых вставок,
то может ли помочь @@ROWCOUNT c генерацией id_2
для всех вставляемых записей?
20 окт 14, 15:19    [16731566]     Ответить | Цитировать Сообщить модератору
 Re: MS SQL: как красиво сделать триггер для автоматической вставки части первичного ключа  [new]
afend
Member

Откуда:
Сообщений: 133
Jaffar,

таких таблиц в базе - около 800...
20 окт 14, 15:24    [16731616]     Ответить | Цитировать Сообщить модератору
 Re: MS SQL: как красиво сделать триггер для автоматической вставки части первичного ключа  [new]
afend
Member

Откуда:
Сообщений: 133
Вопрос: если на таблице два триггера: instead of insert и insert, значит ли это, что первый отменяет второй?
И если нет, то возврат из первого вызовет работу второго? Спасибо!
21 окт 14, 12:45    [16735931]     Ответить | Цитировать Сообщить модератору
 Re: MS SQL: как красиво сделать триггер для автоматической вставки части первичного ключа  [new]
Glory
Member

Откуда:
Сообщений: 104760
afend
значит ли это, что первый отменяет второй?

нет

afend
И если нет, то возврат из первого вызовет работу второго?

You can specify one of two options to control when a DML trigger fires:

- AFTER triggers fire after the triggering action (INSERT, UPDATE, or DELETE), INSTEAD OF triggers and constraints are processed. You can request AFTER triggers by specifying either the AFTER or FOR keywords. Because the FOR keyword has the same effect as AFTER, DML triggers with the FOR keyword are also classified as AFTER triggers.

- INSTEAD OF triggers fire in place of the triggering action and before constraints are processed. If there are AFTER triggers on the table, they will fire after constraint processing. If the constraints are violated, the INSTEAD OF trigger actions are rolled back and the AFTER trigger is not executed.
21 окт 14, 12:51    [16735986]     Ответить | Цитировать Сообщить модератору
 Re: MS SQL: как красиво сделать триггер для автоматической вставки части первичного ключа  [new]
afend
Member

Откуда:
Сообщений: 133
Glory,

спасибо! То есть, в нашем случае, если я проверю, что вставка только для
одного ряда и выполню генерацию второго ключа (т.к. мой приложение шлёт
железно одну запись), то всё ок. В случае нескольких записей я просто делаю
return и срабатывает триггер от другого приложения. Типа:

if @@rowcount=1
begin
--генерация и вставка
end
else return

???
21 окт 14, 12:58    [16736083]     Ответить | Цитировать Сообщить модератору
 Re: MS SQL: как красиво сделать триггер для автоматической вставки части первичного ключа  [new]
Glory
Member

Откуда:
Сообщений: 104760
afend
и срабатывает триггер от другого приложения.

Триггера срабатывабт для операции, а не для приложения.
21 окт 14, 13:05    [16736148]     Ответить | Цитировать Сообщить модератору
 Re: MS SQL: как красиво сделать триггер для автоматической вставки части первичного ключа  [new]
afend
Member

Откуда:
Сообщений: 133
Glory,

это я знаю. Я решил отказаться от триггера и всё это убрать в хранимую процедуру,
которую вызывает моё приложение. Та как оно генерит низкую нагрузку, а писАть
несколько сот триггеров как-то не хочется, то вычисление ключа уберу в ХП.
22 окт 14, 07:05    [16740961]     Ответить | Цитировать Сообщить модератору
Все форумы / Microsoft SQL Server Ответить