SQL 字段值未准确更新
SQL field values not accurately updated
如果记录有更新,则用Y标记,最新版本用null标记。最新更新记录的 CreationDate 应取自先前记录的 ModificationDate。但如屏幕截图所示,该字段未正确更新。有谁知道如何解决这个错误?
如果CreationDate字段值准确,则记录应该是序号。 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)
)
触发器中的 UPDATE
未过滤任何内容,因此它将遍历
返回的所有行
FROM ProcessList
INNER JOIN ProcessListHist ON ProcessList.ID = ProcessListHist.ID
并将每个 ModificationDate
分配给 ProcessList
table,每次都会覆盖先前的值,因此您最终会得到最后一个,无论它是什么。只需要获取修改行的数据,所以需要加入delete
table,像这样:
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
,先得到修改行,然后加入历史table得到新的修改日期
但是如果你注意的话,你加入最后一个table只是为了得到你已经拥有的datetime
(当你调用GETDATE
时),所以你可以简化触发器有点像这样:
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
我看不出有任何理由让您的生活因您当前使用的方式而变得如此复杂。
让我们一一了解。你有以下 table 结构,你有两个操作,即 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
如果是 INSERT,Edit 将为空(这本身就是一个设计缺陷,稍后讨论),ID-Name-Amount-CreationDate 将有一个值,而 ModificationDate 将再次为 NULL。这是一个简单的用例。
Insert into YouTableName values (null,4035,'Rachel Zane',1000,getdate(),null)
Update/Edit
如果是 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
.
如果记录有更新,则用Y标记,最新版本用null标记。最新更新记录的 CreationDate 应取自先前记录的 ModificationDate。但如屏幕截图所示,该字段未正确更新。有谁知道如何解决这个错误?
如果CreationDate字段值准确,则记录应该是序号。 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)
)
触发器中的 UPDATE
未过滤任何内容,因此它将遍历
FROM ProcessList
INNER JOIN ProcessListHist ON ProcessList.ID = ProcessListHist.ID
并将每个 ModificationDate
分配给 ProcessList
table,每次都会覆盖先前的值,因此您最终会得到最后一个,无论它是什么。只需要获取修改行的数据,所以需要加入delete
table,像这样:
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
,先得到修改行,然后加入历史table得到新的修改日期
但是如果你注意的话,你加入最后一个table只是为了得到你已经拥有的datetime
(当你调用GETDATE
时),所以你可以简化触发器有点像这样:
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
我看不出有任何理由让您的生活因您当前使用的方式而变得如此复杂。
让我们一一了解。你有以下 table 结构,你有两个操作,即 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
如果是 INSERT,Edit 将为空(这本身就是一个设计缺陷,稍后讨论),ID-Name-Amount-CreationDate 将有一个值,而 ModificationDate 将再次为 NULL。这是一个简单的用例。
Insert into YouTableName values (null,4035,'Rachel Zane',1000,getdate(),null)
Update/Edit
如果是 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
.