SQL字段值未准确更新

时间:2015-10-01 02:14:51

标签: sql field

如果记录更新,它将标记为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)
)

2 个答案:

答案 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)

我认为没有任何理由让您的生活因您目前的使用方式而变得如此复杂。

让我们逐一理解这一点。您有以下表格结构,并且您有两个操作,即InsertDelete

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