【问题标题】:Insert a different value in underlying table when a view is updated更新视图时在基础表中插入不同的值
【发布时间】:2017-01-16 11:06:05
【问题描述】:

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

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;

是否可以更新基础表,以便 Status validinvalid 内存储为 10基础表的有效列。

请注意,我无法更改表或查询。但是我可以在表格中添加“普通”列。

【问题讨论】:

  • 您是否在寻找额外的 UPDATE 查询,将有效转换为 1 并将无效转换为 0?
  • 你能提供你的视图定义吗?
  • @Tanner 视图只是主表中列的一个子集,但它有一个 WHERE 子句。
  • 所以status是valid的别名?
  • 为什么不在视图上使用而不是更新触发器?

标签: sql sql-server sql-server-2012 views


【解决方案1】:

您可以在视图上使用而不是更新触发器。 当视图上的更新语句完成时,触发器将触发。请注意,不是 trigger 意味着更新将被阻止,您必须自己将更新语句写入下级表。

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

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

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

【讨论】:

  • 我需要在视图中包含 id 列吗?
  • 您已经将它包含在问题中...但是,是的,视图必须包含行标识符(不必是单列,任何具有唯一索引的内容就足够了)
【解决方案2】:

您可以添加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

【讨论】:

    猜你喜欢
    • 2015-08-25
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-09-02
    • 2021-01-09
    • 1970-01-01
    • 2013-05-11
    相关资源
    最近更新 更多