更新视图时在基础 table 中插入不同的值

Insert a different value in underlying table when a view is updated

考虑以下示例,其中我有一个 table 和相应的视图:

Table           | View
T_EmailAddress  | V_EmailAddress
----------------+----------------
ID      INT     | ID
Status  VARCHAR | Status
Valid   INT     |
Column1 VARCHAR | Column1
ColumnN VARCHAR | ColumnN

我有一个程序发出以下查询:

UPDATE V_EmailAddress SET Status = 'valid'   WHERE ID = 1;
UPDATE V_EmailAddress SET Status = 'invalid' WHERE ID = 2;

是否可以更新基础 table 以便 Status validinvalid 存储为 10Valid 列 table.

请注意,我无法更改 table 或查询。但是我可以将 "normal" 列添加到 table.

您可以添加一个UPDATE TRIGGER:

CREATE TRIGGER T_Valid ON T_EmailAddress
INSTEAD OF UPDATE
AS
BEGIN

    UPDATE t
    SET ID = i.ID
        ,Valid = CASE WHEN i.Status = 'Valid' THEN 1 ELSE 0 END
        ,Status = i.Status
        ,Column1 = i.Column1
        ,ColumnN = i.ColumnN
    FROM T_EmailAddress t
        INNER JOIN ON INSERTED i
            ON t.ID = i.ID

END
GO

或者,您可能希望将 Valid 列替换为计算列:

ALTER TABLE T_EmailAddress
DROP COLUMN Valid

ALTER TABLE T_EmailAddress
ADD Valid AS (CASE WHEN Status = 'Valid' THEN 1 ELSE 0 END) PERSISTED

您可以在视图上使用 instead of update 触发器。 每当视图上的更新语句完成时,触发器就会触发。注意,instead of trigger 意味着更新会被阻塞,更新语句必须自己写到底层table。

按照这些思路应该可以解决问题:

CREATE TRIGGER V_EmailAddress_IO_Update ON V_EmailAddress
INSTEAD OF UPDATE
AS
BEGIN

UPDATE t
SET Column1 = i.Column1,
    ColumnN = i.ColumnN,
    Valid = CASE WHEN i.[Status] = 'valid' THEN 1 ELSE 0 END

FROM inserted i 
INNER JOIN T_EmailAddress t ON i.ID = t.ID

END

注意你的更新语句中必须包含视图中所有可以更新的列,否则不会更新。