2013-04-17 3 views
0

У меня есть триггер в моей таблице. Виды, которые записывают все виды на определенную страницу. Этот триггер обновляет таблицу компаний с общими представлениями, которые должны быть получены с помощью вставленного поля. В практической ситуации это никогда не должно случиться так, что одна компания получает несколько видов (так просто выбрать их все и добавив один должен быть достаточно), но мне нравится безопасно кодирование, так что ...Обновление нескольких строк с использованием Count других строк таблицы с разными внешними ключами

компаний: Id, Просмотров

CompanyViews: Id, CompanyID

Необходимое триггерные:

UPDATE Companies 
    SET Views = Views + (SELECT Count(1) FROM INSERTED AS i WHERE i.CompanyId = Id) 
    WHERE Id IN (SELECT DISTINCT(CompanyId) FROM INSERTED) 

Однако это ... не работает. Я не совсем уверен, почему, но в основном предполагаемый результат заключается в следующем: Say, вставленная таблица имеет

Id, CompanyId 
1 2 
2 2 
3 3 
4 5 
5 2 
6 3 

В этом случае, компания 2 получит 3 вид, компания 3 получит 2 мнения и компании 5 получит 1 вид.

Как мне это сделать, когда мой запрос не удался?

EDIT: «Не работает», я имею в виду, значения остаются неизменными. Фактически он вставляет NULL вместо строк, которые он обнаруживает (т. Е. Значения DISTINCT). Если я не буду рассматривать Views +, он просто сделает это 0.

+0

Зачем вам нужно хранить значение в столбце «Виды» через триггер? Вы всегда можете получить эти подсчеты во время выполнения с помощью запроса. Если вычисление агрегата во время выполнения является дорогостоящим, используйте индексированное представление вместо того, чтобы выполнять собственное обслуживание и скрывать это вычисление в триггере. –

+0

Потому что даже индексированный вид будет хитом с миллиардами строк. – NeroS

+0

Что, по-вашему, может показаться, что индексированный просмотр приведет к тому, что ваш триггер не будет? Помните, что индексированное представление только материализует количество строк, идентифицированных уникальным индексом - в этом случае оно будет хранить, самое большее, столько же строк, сколько таблица компаний (вычитая компании с 0 видами). –

ответ

0

Не знаю, почему вы хотите вручную попытаться отследить эти данные с помощью триггера и справиться с проблемами параллелизма, убедитесь, что вы уменьшаете количество удалений в отдельном триггере, и т.д. Вместо этого я бы просто создать индексированное представление, и пусть SQL Server сделать работу для вас:

CREATE VIEW dbo.CompanyViewTotals 
WITH SCHEMABINDING 
AS 
    SELECT CompanyId, Views = COUNT_BIG(*) 
    FROM dbo.CompanyViews 
    GROUP BY CompanyId; 
GO 
CREATE UNIQUE CLUSTERED INDEX x ON dbo.CompanyViewTotals(CompanyId); 
GO 

Да это есть потери на ваши вставках, но так же триггер. Это имеет дополнительное преимущество всегда быть правильным, позволяет вам сбросить триггер и позволяет отказаться от расточительного столбца Views на вашей таблице Companies. Даже без индексированного представления это явно избыточные данные, которые вы уже можете получить без этого столбца.

Если вы действительно не можете обойти все эти дерьмовые ограничения в Entity Framework, вы можете сделать это медленным и ненадежным способом с помощью триггеров. Вам нужно исправить ваш оператор обновления, чтобы использовать правильную корреляцию между inserted и вашей базовой таблицей и правильно учитывать потенциальные значения NULL в базовой таблице.

;WITH cte(CompanyId,NewViews) AS 
(
    SELECT CompanyId, COUNT(CompanyId) 
    FROM inserted 
    GROUP BY CompanyId 
) 
UPDATE c 
    SET c.Views = COALESCE(c.Views, 0) + cte.NewViews 
    FROM cte INNER JOIN dbo.Companies AS c 
    ON cte.CompanyId = c.CompanyId; 
Смежные вопросы