通过视图修改数据

您可以通过视图修改基础基表的数据,其方式与使用 UPDATE、INSERT 和 DELETE 语句,或使用 bcp 实用工具和 BULK INSERT 语句在表中修改数据一样。但是,以下限制应用于更新视图,但不应用于表:

注意注意

下列某些限制不适用于分区视图,且没有任何限制适用于通过 INSTEAD OF 触发器应用的更新。有关详细信息,请参阅本主题后面的“通过视图修改数据的其他选择”。

  • 任何修改(包括 UPDATE、INSERT 和 DELETE 语句)都只能引用一个基表的列。

  • 在视图中修改的列必须直接引用表列中的基础数据。它们不能通过其他方式派生,例如通过:

    • 聚合函数(AVG、COUNT、SUM、MIN、MAX、GROUPING、STDEV、STDEVP、VAR 和 VARP)。

    • 计算,不能通过表达式并使用列计算出其他列。使用集合运算符(UNION、UNION ALL、CROSSJOIN、EXCEPT 和 INTERSECT)形成的列得出的计算结果不可更新。

  • 被修改的列不受 GROUP BY、HAVING 或 DISTINCT 子句的影响。

  • 同时指定了 WITH CHECK OPTION 之后,不能在视图的 select_statement 中的任何位置使用 TOP。

上述限制应用于视图的 FROM 子句中的任何子查询,就像其应用于视图本身一样。通常,SQL Server 必须能够从一个基表的视图定义明确跟踪修改。例如,以下视图不可更新:

USE AdventureWorks2008R2;
GO
CREATE VIEW Sales.TotalSalesContacts
AS
    SELECT p.LastName, 
           SUM(o.TotalDue) AS TotalSales
    FROM Sales.SalesOrderHeader AS o, Person.Person AS p
    WHERE p.BusinessEntityID = o.CustomerID
    GROUP BY LastName;

不能接受对 TotalSalesContacts 的 LastName 列进行修改,因为该列已受到 GROUP BY 子句的影响。如果同一个姓氏有多个实例,则 SQL Server 将无法知道该更新、插入或删除哪个实例。同样,尝试对 TotalSalesContacts 的 TotalSales 列进行修改将返回错误,因为该列是从聚合函数派生的列。SQL Server 不能直接跟踪该列到其基表 SalesOrderHeader。

另外还将应用以下附加准则:

  • 如果在视图定义中使用了 WITH CHECK OPTION 子句,则所有在视图上执行的数据修改语句都必须符合定义视图的 SELECT 语句中所设置的条件。如果使用了 WITH CHECK OPTION 子句,修改行时需注意不让它们在修改完成后从视图中消失。任何可能导致行消失的修改都会被取消,并显示错误。

  • INSERT 语句必须为不允许空值并且没有 DEFAULT 定义的基础表中的所有列指定值。

  • 在基础表的列中修改的数据必须符合对这些列的约束,例如为 Null 性、约束及 DEFAULT 定义等。例如,如果要删除一行,则相关表中的所有基础 FOREIGN KEY 约束必须仍然得到满足,删除操作才能成功。

  • 不能使用由键集驱动的游标更新分布式分区视图(远程视图)。此项限制可通过在基础表上而不是在视图本身上声明游标得到解决。

  • bcp 或 BULK INSERT 和 INSERT ...SELECT * FROM OPENROWSET(BULK...)语句不支持将数据大容量导入到分区视图。但是,您可以使用 INSERT 语句在分区视图中插入多行。有关详细信息,请参阅从视图大容量导出数据或将数据大容量导入视图

  • 不能对视图中的 text、ntext 或 image 列使用 READTEXT 语句和 WRITETEXT 语句。

通过视图修改数据的其他选择

如果本主题的上述限制妨碍直接通过视图修改数据,则可以考虑下列选项:

  • 使用具有支持 INSERT、UPDATE 和 DELETE 语句的逻辑的 INSTEAD OF 触发器。有关详细信息,请参阅设计 INSTEAD OF 触发器

  • 使用修改一个或多个成员表的可更新分区视图。有关详细信息,请参阅创建分区视图

通过视图添加数据

通过视图更改数据

通过视图删除数据

请参阅

概念