我在一家安全承包公司工作,我的数据库中有一个表,用于存储已调整工作PO的小时/次数。对于每个工作日期,财务部门将输入供应商的可计费开始和结束时间,以及客户端的可计费开始和结束时间。大多数情况下,供应商和客户的计费时间是相等的,除非在极少数情况下。
我们的系统工作方式,供应商的开始和结束时间始终更新客户端的开始和结束时间,除非客户端的开始和结束时间与供应商的开始和结束时间不同。为了存储这些信息,我有一个包含这些列的表:
由于供应商和客户端的开始和结束时间通常需要保持彼此同步,我认为我会使用触发器来处理它。因为我需要访问当前值以将它们与新值进行比较,所以看起来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
我想知道的是,如果有更好的方法可以做到这一点。我对所有建议持开放态度,但如果可能的话,我希望将其保留在数据库级别。我也很乐意听到我选择了最好的方法,但出于某种原因我对此表示怀疑。
感谢您的帮助!
答案 0 :(得分:2)
你可以做的一件事......如果你的操作有意义,就是在你的表中添加一个持久的计算列。 (我在你的描述中推断你确实希望存储这个值。如果没有,你不需要持久化选项。)
它可能像coalesce(client_start_time,vender_start_time)。
或者,您可以创建执行相同操作的视图。我并不为观点而疯狂,因为它们容易被滥用,但它们并不总是坏事。
Eithe rway,当它实际上与vender_start_time不同时,你只需输入client_start时间。你可以避免使用触发器。
答案 1 :(得分:1)
我建议在应用程序的业务逻辑层处理它,而不是在数据库中处理它。
我们经历了一个痛苦的时期,将业务规则放在“无处不在” - 在应用程序后端,在存储过程和触发器的数据库中。我们重新设计了我们的方法,并在严格的层次中拆分应用程序。现在开发和维护更加顺畅。在我看来,您描述的任务 - 保持可计费数据同步 - 是业务逻辑的一部分,应该在那里实现。