我的理解是,当创建一个视图时,其定义存储在元数据 sys.tables 中。即sys.views
。
此外,如果您使用SELECT * FROM
它将存储精确的列名,例如SELECT a, b FROM
。
即使您使用“CHECK OPTION” - 它仍然不会根据底层表进行验证。
另一方面,“SCHEMABINDING”将根据底层表进行验证。
我的问题是,当表中的某一列dropped
被替换为同名列时,但是computed
当您查询基于该表的视图时会发生一些奇怪的事情。
这是一个例子。
DROP TABLE IF EXISTS dbo.Test1;
DROP TABLE IF EXISTS dbo.Test2;
GO
CREATE TABLE dbo.Test1
(
Id INT IDENTITY(1,1) PRIMARY KEY ,
Test1Col1 VARCHAR(80) NULL ,
Test1Col2 VARCHAR(80) NULL ,
Test1Col3 VARCHAR(80) NULL
);
CREATE TABLE dbo.Test2
(
Id INT IDENTITY(1,1) PRIMARY KEY ,
Test2Col1 VARCHAR(80) NULL ,
Test2Col2 VARCHAR(80) NULL ,
Test2Col3 VARCHAR(80) NULL ,
Test1Id INT
);
GO
INSERT INTO dbo.Test1
(Test1Col1, Test1Col2, Test1Col3)
VALUES
('Test1Col1Data1', 'Test1Col2Data1', 'Test1Col3Data1') ,
('Test1Col1Data2', 'Test1Col2Data2', 'Test1Col3Data2') ,
('Test1Col1Data3', 'Test1Col2Data3', 'Test1Col3Data3') ;
GO
INSERT INTO dbo.Test2
(Test2Col1, Test2Col2, Test2Col3, Test1Id)
VALUES
('Test2Col1Data1', 'Test2Col2Data1', 'Test2Col3Data1', 1) ,
('Test2Col1Data2', 'Test2Col2Data2', 'Test2Col3Data2', 2) ,
('Test2Col1Data3', 'Test2Col2Data3', 'Test2Col3Data3', 3) ;
GO
创建基于表的视图。
CREATE OR ALTER
VIEW dbo.View1
AS
SELECT T1.*, T2.*
FROM (
SELECT TestId = T.Id
FROM dbo.Test1 T
) T1
INNER JOIN dbo.Test2 T2 ON T2.Test1Id = T1.TestId ;
GO
SELECT * FROM dbo.View1 ;
GO
您将获得以下结果集,
现在我ALTER
表dbo.Test2
。
DROP
列Test2Col3
并将其替换为computed
同名的列。
ALTER TABLE dbo.Test2
DROP COLUMN Test2Col3 ;
ALTER TABLE dbo.Test2
ADD Test2Col3 AS Test2Col1;
GO
现在,当我查询视图时,我得到以下结果集。
SELECT * FROM dbo.View1 ;
GO
列中的数据Test2Col3
看起来Test1Id
已左移 1。
我期望看到的Test2Col3
正在被展示Test1Id
,反之亦然。
这是为什么?
我知道刷新视图或更改视图会更正此问题,但列名并未更改。我已在 SQL-2022 和 Azure SQL 数据库中复制了此问题。