2014-04-10 130 views
3

我正在处理由用户更新的视图。此更新基本上改变了列的值。但现在它没有让我这样做,并产生这样的:更新视图不​​起作用

Update or insert of view or function '' failed because it contains a derived or constant field. 

我知道这是因为我在SELECT语句中的常数,但有什么办法来解决呢?请帮助

这是我认为的代码

Create view Schema.View1 
as 
SELECT 
Convert(Varchar(20),l.jtpName) as JobType, Convert(Varchar(10),' <All> ')as SubCategory , Convert(varchar (3), Case when a.jtpName= l.jtpName and a.subName= ' <All> ' then 'Yes' else 'No' end) As AutoProcess from Schema.JobType l left join Schema.Table1 a on l.jtpName=a.jtpName 
UNION 
SELECT 
Convert(Varchar(20),a.jtpName) as JobType, Convert(Varchar(10),a.subName) as SubCategory, Convert(varchar (3),Case when b.jtpName= a.jtpName and b.subName= a.subName then 'Yes' else 'No' end) As AutoProcess from Schema.SubCategory a left join fds.Table1 b on a.subName=b.subName 

GO 

最后的更新语句:

UPDATE Schema.View1 SET AUTOPROCESS = Case WHEN AUTOPROCESS = 'Yes' Then 'No' END Where JOBTYPE = 'Transport' and SUBCATEGORY= 'Cargo' 

谢谢

回答

4

不能更新列,它是一个结果计算。

根据MSDN,用于视图列可更新的条件之一是这样的:

  • 任何修改,包括UPDATE,INSERT和DELETE语句,必须只从一个基本表中的列。
  • 在视图中修改的列必须直接引用表列中的基础数据。无法通过任何其他方式导出列,例如通过以下方式:
    • 集合函数:AVG,COUNT,SUM,MIN,MAX,GROUPING,STDEV,STDEVP,VAR和VARP。
    • 计算。该列无法从使用其他列的表达式计算。使用集合运算符UNION,UNION ALL,CROSSJOIN,EXCEPT和INTERSECT形成的列相当于计算并且也不可更新。
  • 被修改的列不受GROUP BY,HAVING或DISTINCT子句的影响。
  • TOP不在视图的select_statement的任何位置与WITH CHECK OPTION子句一起使用。

这里不仅做你的视图使用UNION声明,您要更新AutoProcess场实际上是使用两个字段CASE语句的结果。尝试和更新它是没有意义的。

我建议您使用存储过程来执行写入操作。或者,按照达米恩的说法,你也可以在视图上使用一个触发器INSTEAD OF

+0

啊谢谢这个文件非常有帮助。我想我将不得不创建另一个表并将该视图的值提供给它,然后更新表而不是视图。 – crunchynutter

+1

@crunchynutter我不认为你应该创建一个表,以便你可以处理更新操作。改用存储过程。 – Crono

0

有没有办法让sql server从你的转换函数向后工作到原始字段。您无法以这种方式更新视图。

如果视图包含您的jptName和subName字段,那么您可能只能更新这些字段。

+0

他将无法仅更新这些字段,因为它们仍然是“UNION”语句的结果。 – Crono

2

您必须创建一个TRIGGER,然后手动将inserteddeleted伪变化中的更改自己应用于基表。

+0

咦? – Crono

+1

@Crono - 如果OP希望能够针对该视图编写UPDATE,并且SQL Server(非常正确地)认为视图不可更新,唯一可行的方法是在视图上编写触发器手动执行所需的操作。 –

+0

如何在*视图上编写触发器* ??? – Crono