Я бы сказал, что если у вас нет веских причин, хранить значения, которые можно легко вычислить на уровне запроса, является ошибкой.
Это похоже на один из многих случаев, которые я видел, когда люди думают, что они что-то получают, сохраняя значения в одной таблице, которая рассчитывается из значений другой таблицы, но на самом деле все наоборот - теперь у вас есть две точки данных, которые должны быть синхронизированы всегда, и поскольку процесс, синхронизирующий их, является триггером, вы на самом деле не можете это контролировать - например, довольно легко отключить / включить триггеры.
Поэтому, Мой совет вам будет удалить этот триггер все вместе и просто вычислить значение, когда вам нужно.
Обратите внимание, что поскольку SQL Server поддерживает max() over(partition by)
, то есть вам даже не нужно group by
, если вы хотите вычислить максимум столбца.
Обновлено После ваших комментариев к ответу, похоже, у вас есть веская причина сохранить эти значения.
Сказав все это, вот прямой ответ на вопрос, который вы задали.
В триггерах SQL Server база данных позволяет запрашивать две специальные таблицы, называемые inserted
и deleted
. Эти таблицы содержат данные, которые были (или будут в случае instead of
триггеров) вставлены или удалены в таблицу, в которой объявлен триггер.
Обратите внимание, что в SQL Server триггеры запускаются для каждого оператора, а не для строки. Это означает, что таблицы inserted
и deleted
могут содержать 0, 1 или много строк.
Если вы все еще хотите рассчитать значение с использованием триггеров, я бы посоветовал триггер для вставки / обновления и другой триггер для удалений.
Это сделало бы намного более простой код.
В триггере удаления вы оставили присоединение к таблице deleted
:
UPDATE T
SET QARTOD = MaxValue
FROM factMeasures As T
JOIN
(
SELECT d.fkMeasureID, Max(t.RuleValue) As MaxValue
FROM Deleted AS d
LEFT JOIN dt_QCflags As t
ON d.QC_ID = t.QC_ID
GROUP BY d.fkMeasureID
) as D
ON T.MeasureID = D.fkMeasureID
В триггере вставки / обновления вы пишете очень похожий код - но вам не нужно ссылаться на физическая таблица в этом случае, только таблица inserted
:
UPDATE T
SET QARTOD = MaxValue
FROM factMeasures As T
JOIN
(
SELECT fkMeasureID, Max(RuleValue) As MaxValue
FROM Inserted
GROUP BY fkMeasureID
) as I
ON t.MeasureID = I.fkMeasureID
Существует ФАНТАСТИЧЕСКИЙ новый способ сделать это в C# 3.0. Ключ является этим красивым фактом: Перечисления могут иметь дополнительные методы! Так, вот то, что можно сделать:
public enum ArrowDirection
{
North,
South,
East,
West
}
public static class ArrowDirectionExtensions
{
public static UnitVector UnitVector(this ArrowDirection self)
{
// Replace this with a dictionary or whatever you want ... you get the idea
switch(self)
{
case ArrowDirection.North:
return new UnitVector(0, 1);
case ArrowDirection.South:
return new UnitVector(0, -1);
case ArrowDirection.East:
return new UnitVector(1, 0);
case ArrowDirection.West:
return new UnitVector(-1, 0);
default:
return null;
}
}
}
Теперь, можно сделать это:
var unitVector = ArrowDirection.North.UnitVector();
Сладкий! Я только узнал это приблизительно месяц назад, но это - очень хорошее последствие новых функций C# 3.0.
Я вел блог об этом здесь.
Испытайте что-то вроде этого с Атрибутами.
public enum Status {
[Status(Description = "Not Available")]
Not_Available = 1,
[Status(Description = "Available For Game")]
Available_For_Game = 2,
[Status(Description = "Available For Discussion")]
Available_For_Discussion = 3,
}
public class StatusEnumInfo {
private static StatusAttribute[] edesc;
public static String GetDescription(object e)
{
System.Reflection.FieldInfo f = e.GetType().GetField(e.ToString());
StatusEnumInfo.edesc = f.GetCustomAttributes(typeof(StatusAttribute), false) as StatusAttribute[];
if (StatusEnumInfo.edesc != null && StatusEnumInfo.edesc.Length == 1)
return StatusEnumInfo.edesc[0].Description;
else
return String.Empty;
}
public static object GetEnumFromDesc(Type t, string desc)
{
Array x = Enum.GetValues(t);
foreach (object o in x) {
if (GetDescription(o).Equals(desc)) {
return o;
}
} return String.Empty;
}
}
public class StatusAttribute : Attribute {
public String Description { get; set; }
}
public class Implemenation {
public void Run()
{
Status statusEnum = (Status)StatusEnumInfo.GetEnumFromDesc(typeof(Status), "Not Available");
String statusString = StatusEnumInfo.GetDescription(Status.Available_For_Discussion);
}
}
Вместо Описания используйте свое пользовательское Свойство
using System.ComponentModel;
using System.Reflection;
public enum ArrowDirection
{
[Description("Northwards")]
North,
[Description("Southwards")]
South,
[Description("Eastwards")]
East,
[Description("Westwards")]
West
}
...
Создайте дополнительный метод для получения списка описаний:
public static class Enum<T> where T : struct
{
/// <summary>
/// Gets a collection of the enum value descriptions.
/// </summary>
/// <returns></returns>
public static IList<string> GetDescriptions()
{
List<string> descriptions = new List<string>();
foreach (object enumValue in Enum<T>.GetValues())
{
descriptions.Add(((Enum)enumValue).ToDescription());
}
return descriptions;
}
}
Одной вещью, на которую Вы могли посмотреть, является "Безопасный с точки зрения типов Перечислимый" шаблон. Это позволяет Вам создавать перечисление, которое является на самом деле законченным статическим объектом, который может иметь методы/свойства/и т.д..
http://www.javacamp.org/designPattern/enum.html
Joshua Bloch говорит об этом шаблоне в его книге "Эффективный Java". Я использовал его в большом количестве различных ситуаций, и я на самом деле предпочитаю его по простым перечислениям. (Это - агностик языка - это работает в Java, C# или в значительной степени любом языке OO).
Ваш подход статического метода кажется довольно чистым мне. Вы инкапсулируете и перечисление и статический метод в том же классе. Изменения в перечислении централизованы в том едином классе.
Добавление метода к перечислению (согласно Java), кажется, добавляет сложность к чему-то, что является действительно очень простым понятием.
Основанный на атрибуте подход интересен, но еще раз, кажется, сверхусложняет вещи по сравнению со статическим методом.