连接2个具有相似结构的表的视图不会更新(因为它包含派生或常量字段)

时间:2014-08-08 21:20:14

标签: sql-server sql-server-2012

我收到了一个错误:

Msg 4406, Level 16, State 1, Line 5
Update or insert of view or function 'dbo.vwEmployeeAll' failed because it contains a derived or constant field.

然而,在我看来,我没有得出或不变。 我视图中的列都存在。在下面的例子中,这是相当简单的。

-- START TSQL

SET NOCOUNT ON


IF EXISTS ( SELECT * FROM INFORMATION_SCHEMA.TABLES where TABLE_SCHEMA = N'dbo' and TABLE_NAME = N'vwEmployeeAll' and TABLE_TYPE = N'VIEW' ) 
    BEGIN 
    DROP VIEW [dbo].[vwEmployeeAll] 
    END 
GO

IF EXISTS ( SELECT * FROM INFORMATION_SCHEMA.TABLES where TABLE_SCHEMA = N'dbo' and TABLE_NAME = N'Employee' and TABLE_TYPE = N'BASE TABLE' ) 
    BEGIN 
    DROP TABLE [dbo].[EmployeeDeprecated] 
    END 
GO

IF EXISTS ( SELECT * FROM INFORMATION_SCHEMA.TABLES where TABLE_SCHEMA = N'dbo' and TABLE_NAME = N'Employee' and TABLE_TYPE = N'BASE TABLE' ) 
    BEGIN 
    DROP TABLE [dbo].[Employee] 
    END 
GO

IF EXISTS ( SELECT * FROM INFORMATION_SCHEMA.TABLES where TABLE_SCHEMA = N'dbo' and TABLE_NAME = N'Department' and TABLE_TYPE = N'BASE TABLE' ) 
    BEGIN 
    DROP TABLE [dbo].[Department] 
    END 
GO



CREATE TABLE [dbo].[Department](
    [DepartmentUUID] [uniqueidentifier] NOT NULL,
    [TheVersionProperty] [timestamp] NOT NULL,
    [DepartmentName] [nvarchar](80) NULL,
    [CreateDate] [datetime] NOT NULL
    )


ALTER TABLE dbo.[Department] ADD CONSTRAINT PK_Department PRIMARY KEY NONCLUSTERED ([DepartmentUUID]) 
GO

ALTER TABLE [dbo].[Department] ADD CONSTRAINT CK_DepartmentName_Unique UNIQUE ([DepartmentName]) 
GO


CREATE TABLE [dbo].[Employee] ( 

    /* [EmployeeUUID] [uniqueidentifier] NOT NULL, */
    [EmployeeSurrogateKey] int not null IDENTITY(1,2), 
    [ParentDepartmentUUID] [uniqueidentifier] NOT NULL,
    [TheVersionProperty] [timestamp] NOT NULL,
    [SSN] [nvarchar](11) NOT NULL,
    [LastName] [varchar](64) NOT NULL,
    [FirstName] [varchar](64) NOT NULL,
    [CreateDate] [datetime] NOT NULL,
    [UpdateDate] [datetime] NOT NULL,
    [HireDate] [datetime] NOT NULL
    )

GO

ALTER TABLE dbo.Employee ADD CONSTRAINT PK_Employee PRIMARY KEY NONCLUSTERED (EmployeeSurrogateKey) 
GO

ALTER TABLE [dbo].[Employee] ADD CONSTRAINT CK_Employee_SSN_Unique UNIQUE (SSN) 
GO

ALTER TABLE [dbo].[Employee] ADD CONSTRAINT FK_EmployeeToDepartment FOREIGN KEY (ParentDepartmentUUID) REFERENCES dbo.Department (DepartmentUUID) 
GO

/*
ALTER TABLE [dbo].[Employee]
ADD CONSTRAINT [CK_Employee_PK_IsOdd] CHECK ( ( [EmployeeSurrogateKey] % 2 ) != 0)
GO
*/


CREATE TABLE [dbo].[EmployeeDeprecated] ( 

    /*[EmployeeDeprecatedUUID] [uniqueidentifier] NOT NULL,*/
    [EmployeeDeprecatedSurrogateKey] int not null IDENTITY(2,2), 
    [ParentDepartmentUUID] [uniqueidentifier] NOT NULL,
    [TheVersionProperty] [timestamp] NOT NULL,
    [SSN] [nvarchar](11) NOT NULL,
    [LastName] [varchar](64) NOT NULL,
    [FirstName] [varchar](64) NOT NULL,
    [CreateDate] [datetime] NOT NULL,
    [UpdateDate] [datetime] NOT NULL,
    [HireDate] [datetime] NOT NULL
    )

GO

ALTER TABLE dbo.[EmployeeDeprecated] ADD CONSTRAINT PK_EmployeeDeprecated PRIMARY KEY NONCLUSTERED (EmployeeDeprecatedSurrogateKey) 
GO

ALTER TABLE [dbo].[EmployeeDeprecated] ADD CONSTRAINT CK_EmployeeDeprecated_SSN_Unique UNIQUE (SSN) 
GO

ALTER TABLE [dbo].[EmployeeDeprecated] ADD CONSTRAINT FK_EmployeeDeprecatedToDepartment FOREIGN KEY (ParentDepartmentUUID) REFERENCES dbo.Department (DepartmentUUID) 
GO

/*
ALTER TABLE [dbo].[EmployeeDeprecated]
ADD CONSTRAINT [CK_EmployeeDeprecated_PK_IsEven] CHECK ( ( [EmployeeDeprecatedSurrogateKey] % 2 ) = 0)
GO
*/



CREATE VIEW dbo.vwEmployeeAll AS

Select 
    EmployeeSurrogateKey,ParentDepartmentUUID,TheVersionProperty,SSN,LastName,FirstName,CreateDate,UpdateDate,HireDate 
from dbo.Employee
UNION --ALL
Select 
/* EmployeeSurrogateKey =  */
EmployeeDeprecatedSurrogateKey ,ParentDepartmentUUID,TheVersionProperty,SSN,LastName,FirstName,CreateDate,UpdateDate,HireDate
from dbo.EmployeeDeprecated

GO


declare @DepartmentUUID001 uniqueidentifier
select @DepartmentUUID001 = 'DDDDDDDD-0000-0000-0000-000000000101'

declare @DepartmentUUID002 uniqueidentifier
select @DepartmentUUID002 = 'DDDDDDDD-0000-0000-0000-000000000102'

INSERT INTO dbo.Department (DepartmentUUID , DepartmentName , CreateDate )
Select @DepartmentUUID001 , 'Department One' , CURRENT_TIMESTAMP
UNION 
Select @DepartmentUUID002 , 'Department Two' , CURRENT_TIMESTAMP


/*
declare @EmployeeUUID001  uniqueidentifier
select @EmployeeUUID001 = 'EEEEEEEE-0000-0000-0000-000000001001'
declare @EmployeeUUID00A  uniqueidentifier
select @EmployeeUUID00A = 'EEEEEEEE-0000-0000-AAAA-000000009001'
*/


INSERT INTO dbo.Employee (/*EmployeeUUID,*/ParentDepartmentUUID,SSN,LastName,FirstName,CreateDate,UpdateDate,HireDate)
Select /*@EmployeeUUID001 ,*/ @DepartmentUUID001 , '111-11-1111' , 'Smith', 'John' , CURRENT_TIMESTAMP , CURRENT_TIMESTAMP  , '01/01/2001'


INSERT INTO dbo.EmployeeDeprecated(/*EmployeeDeprecatedUUID,*/ParentDepartmentUUID,SSN,LastName,FirstName,CreateDate,UpdateDate,HireDate)
Select /*@EmployeeUUID00A ,*/ @DepartmentUUID002 , '888-88-8888' , 'Jones', 'Mary' , CURRENT_TIMESTAMP , CURRENT_TIMESTAMP  , '02/02/2002'


GO

Select * from dbo.vwEmployeeAll


Update dbo.vwEmployeeAll Set UpdateDate = CURRENT_TIMESTAMP

编辑:

时间戳将其抛出一个循环。

分区视图'ViewUpdateableDB.dbo.vwEmployeeAll'不可更新,因为表'[ViewUpdateableDB]。[dbo]。[Employee]'有一个时间戳列。

2 个答案:

答案 0 :(得分:0)

当主键为Identity时,您无法在使用UNION的视图中更新数据。您必须有一个分区列。否则,它将如何知道要更新哪个表?

IE,您正在使用2个在标识字段上具有主键的表。两个表中的{PK} = 1都可以。 SQL Server如何知道要更新的表。

答案 1 :(得分:0)

这是一个有效的例子......" UNION ALL"和分区栏。

我发布这个,因为有一种特定的方式让它工作....尽管有msdn文档。

  

计算。无法从表达式计算列   使用其他列。使用set运算符形成的列   UNION,UNION ALL,CROSSJOIN,EXCEPT和INTERSECT等于a   计算,也不可更新。

http://msdn.microsoft.com/en-us/library/ms187956%28v=sql.110%29.aspx

根据文档和大多数情况,史蒂夫的答案是正确的,但通过使用分区列,有一种方法可以使其发挥作用。

下面的脚本/示例使用Developer Edition(没有许可的企业版),我针对SqlExpress进行了测试(Microsoft SQL Server 2012 - 11.0.2100.60(X64)     Windows NT 6.1上的Express Edition(64位)(Build 7601:Service Pack 1)  )

Select @@VERSION

-- START TSQL

SET NOCOUNT ON


IF EXISTS ( SELECT * FROM INFORMATION_SCHEMA.TABLES where TABLE_SCHEMA = N'dbo' and TABLE_NAME = N'vwEmployeeAll' and TABLE_TYPE = N'VIEW' ) 
    BEGIN 
    DROP VIEW [dbo].[vwEmployeeAll] 
    END 
GO

IF EXISTS ( SELECT * FROM INFORMATION_SCHEMA.TABLES where TABLE_SCHEMA = N'dbo' and TABLE_NAME = N'Employee' and TABLE_TYPE = N'BASE TABLE' ) 
    BEGIN 
    DROP TABLE [dbo].[EmployeeDeprecated] 
    END 
GO

IF EXISTS ( SELECT * FROM INFORMATION_SCHEMA.TABLES where TABLE_SCHEMA = N'dbo' and TABLE_NAME = N'Employee' and TABLE_TYPE = N'BASE TABLE' ) 
    BEGIN 
    DROP TABLE [dbo].[Employee] 
    END 
GO

IF EXISTS ( SELECT * FROM INFORMATION_SCHEMA.TABLES where TABLE_SCHEMA = N'dbo' and TABLE_NAME = N'Department' and TABLE_TYPE = N'BASE TABLE' ) 
    BEGIN 
    DROP TABLE [dbo].[Department] 
    END 
GO



CREATE TABLE [dbo].[Department](
    [DepartmentUUID] [uniqueidentifier] NOT NULL,
    [TheVersionProperty] [timestamp] NOT NULL,
    [DepartmentName] [nvarchar](80) NULL,
    [CreateDate] [datetime] NOT NULL
    )


ALTER TABLE dbo.[Department] ADD CONSTRAINT PK_Department PRIMARY KEY NONCLUSTERED ([DepartmentUUID]) 
GO

ALTER TABLE [dbo].[Department] ADD CONSTRAINT CK_DepartmentName_Unique UNIQUE ([DepartmentName]) 
GO


CREATE TABLE [dbo].[Employee] ( 

    /* [EmployeeUUID] [uniqueidentifier] NOT NULL, */
    [EmployeeSurrogateKey] int not null IDENTITY(101,2), 
    [EmployeeTablePartitionOrdinal] int not null, 
    [ParentDepartmentUUID] [uniqueidentifier] NOT NULL,
    /*[TheVersionProperty] [timestamp] NOT NULL,*/
    [SSN] [nvarchar](11) NOT NULL,
    [LastName] [varchar](64) NOT NULL,
    [FirstName] [varchar](64) NOT NULL,
    [CreateDate] [datetime] NOT NULL,
    [UpdateDate] [datetime] NOT NULL,
    [HireDate] [datetime] NOT NULL
    )

GO

ALTER TABLE dbo.Employee ADD CONSTRAINT PK_Employee PRIMARY KEY NONCLUSTERED (EmployeeSurrogateKey,EmployeeTablePartitionOrdinal) 
GO

ALTER TABLE [dbo].[Employee] ADD CONSTRAINT CK_Employee_SSN_Unique UNIQUE (SSN) 
GO

ALTER TABLE [dbo].[Employee] ADD CONSTRAINT FK_EmployeeToDepartment FOREIGN KEY (ParentDepartmentUUID) REFERENCES dbo.Department (DepartmentUUID) 
GO

/*
ALTER TABLE [dbo].[Employee]
ADD CONSTRAINT [CK_Employee_PK_IsOdd] CHECK ( ( [EmployeeSurrogateKey] % 2 ) != 0)
GO
*/

/*
ALTER TABLE [dbo].[Employee] WITH CHECK ADD  CONSTRAINT [CK_Employee_PK_IsOdd] 
CHECK ( ( [EmployeeSurrogateKey] % 2 ) != 0)
GO
*/

ALTER TABLE [dbo].[Employee] WITH CHECK ADD  CONSTRAINT [CK_EmployeeTablePartitionOrdinal_Is_One] 
CHECK ( [EmployeeTablePartitionOrdinal] = 1 )
GO


CREATE TABLE [dbo].[EmployeeDeprecated] ( 

    /*[EmployeeDeprecatedUUID] [uniqueidentifier] NOT NULL,*/
    [EmployeeDeprecatedSurrogateKey] int not null IDENTITY(102,2), 
    [EmployeeTablePartitionOrdinal] int not null, 
    [ParentDepartmentUUID] [uniqueidentifier] NOT NULL,
    /*[TheVersionProperty] [timestamp] NOT NULL,*/ /* Partitioned view 'ViewUpdateableDB.dbo.vwEmployeeAll' is not updatable because table '[ViewUpdateableDB].[dbo].[Employee]' has a timestamp column. */
    [SSN] [nvarchar](11) NOT NULL,
    [LastName] [varchar](64) NOT NULL,
    [FirstName] [varchar](64) NOT NULL,
    [CreateDate] [datetime] NOT NULL,
    [UpdateDate] [datetime] NOT NULL,
    [HireDate] [datetime] NOT NULL
    )

GO

ALTER TABLE dbo.[EmployeeDeprecated] ADD CONSTRAINT PK_EmployeeDeprecated PRIMARY KEY NONCLUSTERED (EmployeeDeprecatedSurrogateKey,EmployeeTablePartitionOrdinal) 
GO

ALTER TABLE [dbo].[EmployeeDeprecated] ADD CONSTRAINT CK_EmployeeDeprecated_SSN_Unique UNIQUE (SSN) 
GO

ALTER TABLE [dbo].[EmployeeDeprecated] ADD CONSTRAINT FK_EmployeeDeprecatedToDepartment FOREIGN KEY (ParentDepartmentUUID) REFERENCES dbo.Department (DepartmentUUID) 
GO

/*
ALTER TABLE [dbo].[EmployeeDeprecated]
ADD CONSTRAINT [CK_EmployeeDeprecated_PK_IsEven] CHECK ( ( [EmployeeDeprecatedSurrogateKey] % 2 ) = 0)
GO
*/
/*
ALTER TABLE [dbo].[EmployeeDeprecated] WITH CHECK ADD  CONSTRAINT [CK_EmployeeDeprecated_PK_IsEven] 
CHECK  ( ( [EmployeeDeprecatedSurrogateKey] % 2 ) = 0)
GO
*/

ALTER TABLE [dbo].[EmployeeDeprecated] WITH CHECK ADD  CONSTRAINT [CK_EmployeeTablePartitionOrdinal_Is_Two] 
CHECK ( [EmployeeTablePartitionOrdinal] = 2 )
GO


CREATE VIEW dbo.vwEmployeeAll AS

Select 
    EmployeeSurrogateKey,EmployeeTablePartitionOrdinal,ParentDepartmentUUID,SSN,LastName,FirstName,CreateDate,UpdateDate,HireDate 
from dbo.Employee
UNION ALL
Select 
EmployeeSurrogateKey =
EmployeeDeprecatedSurrogateKey,EmployeeTablePartitionOrdinal,ParentDepartmentUUID,SSN,LastName,FirstName,CreateDate,UpdateDate,HireDate
from dbo.EmployeeDeprecated

GO


declare @DepartmentUUID001 uniqueidentifier
select @DepartmentUUID001 = 'DDDDDDDD-0000-0000-0000-000000000101'

declare @DepartmentUUID002 uniqueidentifier
select @DepartmentUUID002 = 'DDDDDDDD-0000-0000-0000-000000000102'

INSERT INTO dbo.Department (DepartmentUUID , DepartmentName , CreateDate )
Select @DepartmentUUID001 , 'Department One' , CURRENT_TIMESTAMP
UNION 
Select @DepartmentUUID002 , 'Department Two' , CURRENT_TIMESTAMP


/*
declare @EmployeeUUID001  uniqueidentifier
select @EmployeeUUID001 = 'EEEEEEEE-0000-0000-0000-000000001001'
declare @EmployeeUUID00A  uniqueidentifier
select @EmployeeUUID00A = 'EEEEEEEE-0000-0000-AAAA-000000009001'
*/


INSERT INTO dbo.Employee (/*EmployeeUUID,*/ParentDepartmentUUID,SSN,LastName,FirstName,CreateDate,UpdateDate,HireDate,EmployeeTablePartitionOrdinal)
Select /*@EmployeeUUID001 ,*/ @DepartmentUUID001 , '111-11-1111' , 'Smith', 'John' , CURRENT_TIMESTAMP , CURRENT_TIMESTAMP  , '01/01/2001' , 1


INSERT INTO dbo.EmployeeDeprecated(/*EmployeeDeprecatedUUID,*/ParentDepartmentUUID,SSN,LastName,FirstName,CreateDate,UpdateDate,HireDate,EmployeeTablePartitionOrdinal)
Select /*@EmployeeUUID00A ,*/ @DepartmentUUID002 , '888-88-8888' , 'Jones', 'Mary' , CURRENT_TIMESTAMP , CURRENT_TIMESTAMP  , '02/02/2002' , 2


GO

Select * from dbo.vwEmployeeAll


Update dbo.vwEmployeeAll Set UpdateDate = CURRENT_TIMESTAMP


Update dbo.vwEmployeeAll Set LastName = 'Henderson' where EmployeeSurrogateKey = 1

Update dbo.vwEmployeeAll Set UpdateDate = CURRENT_TIMESTAMP where EmployeeSurrogateKey = 2