如果记录更新,它将标记为Y,最新版本将标记为null。最新更新记录的CreationDate应取自上一记录的ModificationDate。但是如截图所示,该字段未正确更新。有谁知道如何解决这个错误?
如果CreationDate字段值准确,则记录的顺序应为no。 6,8,7
CREATE TRIGGER CloneAfterUpdate ON ProcessList
AFTER UPDATE
AS
IF (UPDATE (Amount) OR UPDATE (NAME))
BEGIN
INSERT INTO ProcessListHist (
ID
,NAME
,Amount
,CreationDate
,Edited
,ModificationDate
)
SELECT ID
,NAME
,Amount
,CreationDate
,'Y'
,GETDATE()
FROM deleted
UPDATE ProcessList
SET ProcessList.CreationDate = ProcessListHist.ModificationDate
FROM ProcessList
INNER JOIN ProcessListHist ON ProcessList.ID = ProcessListHist.ID
END
UPDATE ProcessList
SET Amount = 9800
WHERE NAME = 'Rachel'
SELECT *
FROM ProcessList
UNION ALL
SELECT *
FROM ProcessListHist
ORDER BY ID ASC ,CreationDate ASC
---已更新---
CREATE TABLE dbo.ProcessList
(
Edited varchar(1),
ID integer NOT NULL,
Name varchar(30) NOT NULL,
Amount smallmoney NOT NULL,
CreationDate datetime DEFAULT GETDATE(),
ModificationDate datetime,
PRIMARY KEY (ID, CreationDate)
)
CREATE TABLE dbo.ProcessListHist
(
Edited varchar(1),
ID integer NOT NULL,
Name varchar(30) NOT NULL,
Amount smallmoney NOT NULL,
CreationDate datetime NOT NULL,
ModificationDate datetime,
PRIMARY KEY (ID, CreationDate)
)
答案 0 :(得分:1)
触发器中的UPDATE
未过滤任何内容,因此它将遍历
FROM ProcessList
INNER JOIN ProcessListHist ON ProcessList.ID = ProcessListHist.ID
并将每个ModificationDate
分配给ProcessList
表,每次都覆盖以前的值,因此最终得到最后一个,无论是什么。您只需要获取修改行的数据,因此您需要加入delete
表,如下所示:
UPDATE PL
SET PL.CreationDate = PLH.ModificationDate
FROM ProcessList PL
INNER JOIN deleted on PL.ID = deleted.ID AND PL.CreationDate = deleted.CreationDate
INNER JOIN ProcessListHist PLH ON PL.ID = PLH.ID AND PLH.CreationDate = deleted.CreationDate
通过加入delete
,您首先获得修改后的行,然后您可以加入历史记录表以获取新的修改日期。
但是如果你注意了,那么你加入最后一张表只是为了得到你已经拥有的datetime
(当你调用GETDATE
时),所以你可以像这样简化触发器:< / p>
DECLARE @Now DATETIME
SELECT @Now = GETDATE()
INSERT INTO ProcessListHist (
ID
,NAME
,Amount
,CreationDate
,Edited
,ModificationDate
)
SELECT ID
,NAME
,Amount
,CreationDate
,'Y'
,@Now
FROM deleted
UPDATE PL
SET PL.CreationDate = @Now
FROM ProcessList PL
INNER JOIN deleted on PL.ID = deleted.ID AND PL.CreationDate = deleted.CreationDate
ProcessList
是否需要ModificationDate
字段?为什么需要Edited
字段?从我看到的情况来看,它始终是NULL
,另一个是Y
。如果你全部删除它们,你可以这样做最后一个查询:
SELECT NULL AS Edited, ID, Name, Amount, CreationDate, NULL AS ModificationDate
FROM ProcessList
UNION ALL
SELECT 'Y', ID, Name, Amount, CreationDate, ModificationDate
FROM ProcessListHist
ORDER BY ID ASC ,CreationDate ASC
答案 1 :(得分:1)
我认为没有任何理由让您的生活因您目前的使用方式而变得如此复杂。
让我们逐一理解这一点。您有以下表格结构,并且您有两个操作,即Insert
和Delete
。
CREATE TABLE dbo.ProcessList
(
Edited varchar(1),
ID integer NOT NULL,
Name varchar(30) NOT NULL,
Amount smallmoney NOT NULL,
CreationDate datetime DEFAULT GETDATE(),
ModificationDate datetime,
PRIMARY KEY (ID, CreationDate)
)
插入强>
在INSERT的情况下,Edit将为null(这本身就是设计缺陷,稍后将讨论),ID-Name-Amount-CreationDate将具有值,并且ModificationDate将再次为NULL。这是一个简单的用例。
Insert into YouTableName values (null,4035,'Rachel Zane',1000,getdate(),null)
<强>更新/修改
如果是EDIT,您需要将EDIT列更新为“Y”,然后您将更新其余字段,只需将ModificationDate
复制到CreationDate
,如下所示
Update table
set Edit = 'Y',
Name = <NewNameIfAny>,
Amount = <NewAmountIfAny>,
CreationDate = ModificationDate,
ModificationDate = Getdate()
就是这样,你就完成了,这样你就不需要任何Trigger
了。而且我没有看到任何相同的用例。您可以阅读here用例来使用触发器。
DesignFlaw :当您知道在EDIT列中要么是'Y'或'null'时,为什么不用bit
类型来表示它是比什么都快。比特将作为你的旗帜。最初,您可以将其标记为False (0)
,并且无论何时进行任何编辑,都会将其更新为True (1)
。而已。您可以将列重命名为IsEdited
。