Добро пожаловать в форум, Guest  >>   Войти | Регистрация | Поиск | Правила | В избранное | Подписаться
Все форумы / Microsoft SQL Server Новый топик    Ответить
 AFTER INSERT UPDATE(COUNT SERVICES)  [new]
alex212121
Member

Откуда:
Сообщений: 54
Добрый вечер
и так проблема такая :

есть таблица service (обслуживание клиентов) и таблица clients (перечень клиентов)
цель - после каждого сделанного СЕРВИСА (ИНСЕРТА В таблицу service) делался бы АПДЕЙТ и в таблице (clients) у каждого клиента обновлялся бы столб count_services, количество сделанных service-ов (обслуживаний)...

пишу код
запускается триггер
но когда делаю инсерт в (clients) ничего не меняется и не прибавляется

прошу помочь
заранее спасибо





create table service
(
service_id INT NOT NULL PRIMARY KEY IDENTITY(1,1),
client_id int
)


create table clients
(
clients_id INT NOT NULL PRIMARY KEY IDENTITY(1,1),
name nvarchar(100),
surname nvarchar(100),
count_services int
)

create trigger COUNT_SERVICES_IN_CLIENTS
on Service after insert, update
as
begin

if ((exists(select * from [INSERTED])))
return;

if ((exists(
select * from Service S
where ((S.client_id is null))
)))
return;

update C
set C.[count_services]=(select COUNT(S.client_id_ID) from SERVICE as S where S.client_id_ID=C.[Clients_ID])
from Service S, Clients C
where ((S.[client_id_ID] is NOT null))
;

end
go
30 июн 12, 23:40    [12799780]     Ответить | Цитировать Сообщить модератору
 Re: AFTER INSERT UPDATE(COUNT SERVICES)  [new]
Сид
Member

Откуда: Москва
Сообщений: 305
alex212121,

create trigger COUNT_SERVICES_IN_CLIENTS
on Service after insert, update
as
begin

if ((exists(select * from [INSERTED])))
return;

bla bla bla


Это делает триггер бесполезным, ибо и при insert, и при update всегда что-то есть в inserted.
С таким же успехом можно было бы не создавать триггер вообще.

if ((exists(
select * from Service S
where ((S.client_id is null))
))) 
return;


Т.е. если вдруг случится ситуация, при которой в таблице Service в столбце client_id окажется NULL, триггер вообще должен перестать работать, ведь так?

update C
set C.[count_services]=(select COUNT(S.client_id_ID) from SERVICE as S where S.client_id_ID=C.[Clients_ID])
from Service S, Clients C 
where ((S.[client_id_ID] is NOT null))


Не страшно такой апдейт делать? Конечно, сейчас 2 часа ночи, и я мог что-то не заметить, например условие соединения... А пока что я вижу апдейт с декартовым произведением, что уже при небольшом наборе данных и относительно небольшой нагрузке положит твою систему на лопатки.

Остальные странности, о которых можно было бы сказать, выходят за рамки вопроса.
1 июл 12, 02:09    [12800060]     Ответить | Цитировать Сообщить модератору
 Re: AFTER INSERT UPDATE(COUNT SERVICES)  [new]
alex212121
Member

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

Сид, привет

то есть есть этот триггер делать бесполезно. то как по другому можно подсчитывать автоматически количество сервисов для каждого клиента?

Можно и так делать, но тут всё выходит отдельно, а мне нужно чтобы в месте с основной таблицей было.


select temp.name, temp.surname from
(
select p.name as name, p.surname AS surname, ordercount=
(select COUNT(o.person_id) from Orders as o where o.person_id=p.person_id) as ordercount
from Persons as p
) as temp
where temp.ordercount is not null

1 июл 12, 12:00    [12800335]     Ответить | Цитировать Сообщить модератору
 Re: AFTER INSERT UPDATE(COUNT SERVICES)  [new]
aleks2
Guest
Создай Indexed View

CREATE VIEW [dbo].[Services_Count]
with schemabinding
AS
SELECT     client_id, COUNT_BIG(*) AS count_services
FROM         dbo.service
GROUP BY client_id

GO
create unique clustered index IDX_Services_Count on [Services_Count] (client_id);

GO

-- Это можешь оформить как View.
SELECT c.clients_id, c.name, c.surname, sc.count_services  FROM clients c INNER JOIN [dbo].[Services_Count] sc WITH(noexpand)  on c.clients_id = sc.client_id
1 июл 12, 12:49    [12800381]     Ответить | Цитировать Сообщить модератору
 Re: AFTER INSERT UPDATE(COUNT SERVICES)  [new]
RubinDm
Member

Откуда:
Сообщений: 461
create trigger COUNT_SERVICES_IN_CLIENTS
  on Service after insert, update
  -- Почему Вы не учитываете здесь возможность УДАЛЕНИЕЯ услуг?
as
begin
  -- не слушайте никого и оставьте эту проверку на этом месте.
  if (not(exists(select * from [INSERTED])))
    return;
  
  -- не слушайте никого и оставьте эту проверку на этом месте.
  if (not(update client_id))
    return;
  
  -- Понятно, что именно имелось виду, но так проверять нельзя.
  -- Могут быть и многострочные инсерты или апдейты.
  -- Если среди множества строк в [inserted]
  -- окажется хотя бы одна where client_id is null,
  -- то триггер прекратит свою работу и не обработает
  -- остальные записи из [inserted]  where client_id is NOT null.
  -- Возможно, именно на этом месте Вы и спотыкаетесь.
/* if ((exists(
    select * from Service S
    where ((S.client_id is null))
  ))) 
    return;*/
  -- Что на самом деле Вам интересно проверить?
  -- 1) Наличие    записей где client_id is     null ?
  -- или все-таки
  -- 2) Отсутствие записей где client_id is NOT null ?
  -- мое имхо 2: 
  if(not(exists(select * from [inserted] where client_id is NOT null))
    return;
  
  -- Обновление клиента я сделал бы так:
  update C
  set C.[count_services]=(select COUNT(*) from SERVICE as S where S.client_id_ID=C.[Clients_ID])
  from Clients C
  where C.client_id in (select [new].[client_id] from [inserted] [new])
  ;
  
end
go
1 июл 12, 13:09    [12800399]     Ответить | Цитировать Сообщить модератору
 Re: AFTER INSERT UPDATE(COUNT SERVICES)  [new]
qwerty112
Guest
RubinDm
 create trigger COUNT_SERVICES_IN_CLIENTS
  on Service after insert, update
 ....
  -- не слушайте никого и оставьте эту проверку на этом месте.
  if (not(exists(select * from [INSERTED])))
    return;

зачем это ??
как может быть "пустая" таблица INSERTED, в триггере "after insert, update" ?
1 июл 12, 13:14    [12800404]     Ответить | Цитировать Сообщить модератору
 Re: AFTER INSERT UPDATE(COUNT SERVICES)  [new]
Гавриленко Сергей Алексеевич
Member

Откуда:
Сообщений: 37254
qwerty112
как может быть "пустая" таблица INSERTED, в триггере "after insert, update" ?
Легко. Задание на дом: поразмыслить, как действительно может.
1 июл 12, 13:34    [12800421]     Ответить | Цитировать Сообщить модератору
 Re: AFTER INSERT UPDATE(COUNT SERVICES)  [new]
RubinDm
Member

Откуда:
Сообщений: 461
Гавриленко Сергей Алексеевич
qwerty112
как может быть "пустая" таблица INSERTED, в триггере "after insert, update" ?
Легко. Задание на дом: поразмыслить, как действительно может.
+1 и будь моя воля - заколотил бы ответ в faq.
1 июл 12, 13:52    [12800442]     Ответить | Цитировать Сообщить модератору
 Re: AFTER INSERT UPDATE(COUNT SERVICES)  [new]
qwerty112
Guest
Гавриленко Сергей Алексеевич
qwerty112
как может быть "пустая" таблица INSERTED, в триггере "after insert, update" ?
Легко. Задание на дом: поразмыслить, как действительно может.

"сдаёмсу",
нет у меня вариантов ..

зы
подозреваю, что вы сейчас расскажете про merge
1 июл 12, 13:58    [12800448]     Ответить | Цитировать Сообщить модератору
 Re: AFTER INSERT UPDATE(COUNT SERVICES)  [new]
qwerty112
Guest
qwerty112
зы
подозреваю, что вы сейчас расскажете про merge

имелось в виду, что его (merge) - мне проверить не на чём
1 июл 12, 13:59    [12800449]     Ответить | Цитировать Сообщить модератору
 Re: AFTER INSERT UPDATE(COUNT SERVICES)  [new]
Гавриленко Сергей Алексеевич
Member

Откуда:
Сообщений: 37254
Это не merge.
1 июл 12, 14:36    [12800493]     Ответить | Цитировать Сообщить модератору
 Re: AFTER INSERT UPDATE(COUNT SERVICES)  [new]
invm
Member

Откуда: Москва
Сообщений: 9836
qwerty112,

Триггер срабатывает на инструкцию. Соответственно, если инструкция затронула 0 строк, то inserted/deleted будут пустые.
1 июл 12, 14:36    [12800495]     Ответить | Цитировать Сообщить модератору
 Re: AFTER INSERT UPDATE(COUNT SERVICES)  [new]
aleks2
Guest
qwerty112
"сдаёмсу",
нет у меня вариантов ..


update aTable set aField = aField
where 1 = 2
1 июл 12, 14:36    [12800497]     Ответить | Цитировать Сообщить модератору
 Re: AFTER INSERT UPDATE(COUNT SERVICES)  [new]
qwerty112
Guest
 create table test (id int, txt varchar(10))
 go

 create trigger iu_test
 on test after insert, update
 as
 begin
 	set nocount on
 	print 'haba-haba'
 	declare @cnt int
 	select @cnt=count(*) from inserted
 	print @cnt
 end
 go

 create table test1 (id int, txt varchar(10))
 go

invm
qwerty112,

Триггер срабатывает на инструкцию. Соответственно, если инструкция затронула 0 строк, то inserted/deleted будут пустые.

где ??
print '--- 1'
insert into test
select 1, '1'
where 1=1
go

print '--- 2'
insert into test
select 1, '1'
where 1=0
go

--- 1

(1 row(s) affected)

haba-haba
1
--- 2
 ???????
(0 row(s) affected)


aleks2
qwerty112
"сдаёмсу",
нет у меня вариантов ..


update aTable set aField = aField
where 1 = 2

тоже - пусто ....
delete from test
go

print '--- 1'
insert into test
select 1, '1'
where 1=1
go

print '--- 2'
insert into test
select 1, '1'
where 1=0
go

print '--- 3'
update test
set txt=txt
where 1=0
go

(1 row(s) affected)

--- 1

(1 row(s) affected)

haba-haba
1
--- 2

(0 row(s) affected)

--- 3
 ???
(0 row(s) affected)

это проверял на этом
select @@version

Microsoft SQL Server  2000 - 8.00.194 (Intel X86) 
	Aug  6 2000 00:57:48 
	Copyright (c) 1988-2000 Microsoft Corporation
	Desktop Engine on Windows NT 5.1 (Build 2600: Service Pack 3)

-----------------

вот так "выпросил" что-то ...
--- 1
print '--- 1'
insert into test
output inserted.id, inserted.txt INTO test1
select 1, '1'
where 1=1

--- 2
print '--- 2'
insert into test
output inserted.id, inserted.txt INTO test1
select 1, '1'
where 1=0

--- 1
haba-haba
1

(1 row(s) affected)
--- 2
haba-haba
0

(0 row(s) affected)

на таком
select @@version

Microsoft SQL Server 2005 - 9.00.1399.06 (Intel X86) 
	Oct 14 2005 00:33:37 
	Copyright (c) 1988-2005 Microsoft Corporation
	Express Edition on Windows NT 5.1 (Build 2600: Service Pack 3)
1 июл 12, 15:00    [12800529]     Ответить | Цитировать Сообщить модератору
 Re: AFTER INSERT UPDATE(COUNT SERVICES)  [new]
qwerty112
Guest
бугага !
на 2005-ом - и все остальные варианты "выполняются"
delete from test
go

print '--- 1'
insert into test
select 1, '1'
where 1=1
go

print '--- 2'
insert into test
select 1, '1'
where 1=0
go

print '--- 3'
update test
set txt=txt
where 1=0
go

(2 row(s) affected)
--- 1
haba-haba
1

(1 row(s) affected)
--- 2
haba-haba
0

(0 row(s) affected)
--- 3
haba-haba
0

(0 row(s) affected)


а почему так ?
1 июл 12, 15:08    [12800538]     Ответить | Цитировать Сообщить модератору
 Re: AFTER INSERT UPDATE(COUNT SERVICES)  [new]
Гавриленко Сергей Алексеевич
Member

Откуда:
Сообщений: 37254
Потому что не надо ничего тестить на релизной версии, которой аж 4 сервиспака было выпущено, а вы ни один не удосужились поставить. Там и 2*2 = 5 может запросто получиться.
1 июл 12, 15:10    [12800540]     Ответить | Цитировать Сообщить модератору
 Re: AFTER INSERT UPDATE(COUNT SERVICES)  [new]
alex212121
Member

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


привет
вообщето задачка такая чтобы в таблице где список клиентов, бол бы столб в котором смогу видеть у какого кдиента сколько заказов
я пытаюсь но он пишет ошибки в местах которые болдом выделены




create trigger COUNT_SERVICES_IN_CLIENTS
on Service after insert, update

as
begin

if (not(exists(select * from [INSERTED])))
return;

if (not(update Clients)
return;


if(not(exists(select * from [inserted] where (SELECT C.Clients_ID from Clients as C) is NOT null))
return;


update C
set C.[სერვისების_რაოდენობა]=(select COUNT(*) from SERVICE as S where S.კლიენტის_ID=C.[Clients_ID])
from Clients C
where C.Clients_ID in (select new.Clients_ID from inserted new)
;

end
go
2 июл 12, 20:50    [12806500]     Ответить | Цитировать Сообщить модератору
 Re: AFTER INSERT UPDATE(COUNT SERVICES)  [new]
alex212121
Member

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


ВОТ ПОЛУЧИЛОСЬ

create trigger COUNT_SERVICES_IN_CLIENTS1
on Service after insert, update

as
begin

if (not(exists(select * from [INSERTED])))
return;


update C
set C.[სერვისების_რაოდენობა]=(select COUNT(*) from SERVICE as S where S.კლიენტის_ID=C.[Clients_ID])
from Clients C
where C.Clients_ID in (select Clients_ID from inserted)
;

end
go
2 июл 12, 20:55    [12806509]     Ответить | Цитировать Сообщить модератору
 Re: AFTER INSERT UPDATE(COUNT SERVICES)  [new]
alex212121
Member

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

ВСЕМ БОЛЬШОЕ СПАСИБО
2 июл 12, 20:56    [12806512]     Ответить | Цитировать Сообщить модератору
Все форумы / Microsoft SQL Server Ответить