Лучшая альтернатива INSTEAD OF INSERT, триггер UPDATE - PullRequest
3 голосов
/ 13 августа 2011

Я работаю в компании-подрядчике по обеспечению безопасности, и в моей базе данных есть таблица, в которой хранятся скорректированные часы / время для отработанных ПО.Для каждой отработанной даты финансовый отдел будет указывать начальное и конечное время оплаты для поставщика, а также начальное и конечное время оплаты для клиента.В большинстве случаев время оплаты поставщика и клиента одинаково, за исключением редких случаев.

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

  • JobID
  • PostNumber
  • StartTime (время начала поставщика)
  • ClosingTime (время начала поставщика)
  • ClientStartTime
  • ClientClosingTime

Поскольку время начала и окончания работы поставщика и клиента обычно должно синхронизироваться, я решил, чтоиспользуйте триггер, чтобы справиться с этим.Поскольку мне нужен доступ к текущим значениям, чтобы сравнить их с новыми значениями, кажется, что триггер INSTEAD OF INSERT, UPDATE - это путь, за исключением того, что я не без ума от триггеров, во-первых, и полагаюсь натриггер для выполнения всех моих вставок и обновлений в этой таблице заставляет меня нервничать.Может быть, это иррациональный страх, который у меня есть, но я обычно стараюсь держаться подальше от триггеров, когда могу.В этом случае, однако, это кажется лучшим вариантом.

Вот мой триггер, который должен прояснить логику:

ALTER TRIGGER [dbo].[<UpdateAdjustedHours>]
   ON  [dbo].[<AdjustedHoursTable>] 
   INSTEAD OF INSERT, UPDATE
AS 
BEGIN

    IF (NOT EXISTS(SELECT CurrentValues.JobID FROM WorkOrderDetailAdjustment CurrentValues, Inserted NewValues WHERE CurrentValues.JobID = NewValues.JobID AND CurrentValues.PostNumber = NewValues.PostNumber))
    BEGIN

        INSERT INTO WorkOrderDetailAdjustment
            SELECT  Inserted.JobID,
                    Inserted.PostNumber,
                    Inserted.StartTime,
                    Inserted.ClosingTime,
                    ISNULL(Inserted.ClientStartTime, Inserted.StartTime),
                    ISNULL(Inserted.ClientClosingTime, Inserted.ClosingTime)    
            FROM    Inserted                

    END
    ELSE BEGIN

        UPDATE  CurrentValues
        SET     CurrentValues.StartTime = ISNULL(NewValues.StartTime, CurrentValues.StartTime),
                CurrentValues.ClosingTime = ISNULL(NewValues.ClosingTime, CurrentValues.ClosingTime),
                CurrentValues.ClientStartTime = (
                    CASE WHEN DATEDIFF(SECOND, CurrentValues.ClientStartTime, CurrentValues.StartTime) != 0 THEN 
                        ISNULL(NewValues.ClientStartTime, CurrentValues.ClientStartTime) 
                    ELSE 
                        NewValues.StartTime 
                    END
                ),
                CurrentValues.ClientClosingTime = (
                    CASE WHEN DATEDIFF(SECOND, CurrentValues.ClientClosingTime, CurrentValues.ClosingTime) != 0 THEN
                        ISNULL(NewValues.ClientClosingTime, CurrentValues.ClientClosingTime)
                    ELSE
                        NewValues.ClosingTime
                    END
                )
        FROM    WorkOrderDetailAdjustment CurrentValues, Inserted NewValues
        WHERE   CurrentValues.JobID = NewValues.JobID AND CurrentValues.PostNumber = NewValues.PostNumber

    END

END

Мне интересно, есть ли лучший способсделать это.Я открыт для всех предложений, но если возможно, я бы хотел сохранить это на уровне базы данных.Я также готов услышать, что я выбрал наилучший из возможных способов сделать это, но по некоторым причинам я сомневаюсь в этом.

Спасибо за вашу помощь!

Ответы [ 2 ]

2 голосов
/ 13 августа 2011

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

Это может быть что-то вроде coalesce (client_start_time, vender_start_time).

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

В любом случае, вам нужно будет ввести время client_start только тогда, когда оно фактически отличается от vender_start_time. И вы можете избежать использования триггера.

1 голос
/ 10 сентября 2011

Я бы предложил обрабатывать его на уровне бизнес-логики вашего приложения, а не в базе данных.

Мы пережили мучительное время, когда бизнес-правила размещались "везде" - в бэкэнде приложения, в базе данных вхранимые процедуры и триггеры.Мы переработали наш подход и разделили приложения на строгие уровни.Разработка и сопровождение теперь намного плавнее.По моему мнению, задача, которую вы описали, - обеспечение синхронизации оплачиваемых данных - является частью бизнес-логики и должна быть реализована там.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...