MS SQL:通过包含新表中的其他列来更改索引视图
Posted
技术标签:
【中文标题】MS SQL:通过包含新表中的其他列来更改索引视图【英文标题】:MS SQL: alter indexed view by including additional columns from new table 【发布时间】:2020-03-23 00:03:15 【问题描述】:我需要通过包含来自新创建的表的附加列值来更新现有的 MS SQL 索引视图。 索引视图:
CREATE OR ALTER VIEW [dbo].[MySelectionInfo]
WITH schemabinding
AS
SELECT C.Id id0,
C.Code Code1,
C.Name Name2,
C.ProgramLevel Level3,
C.Department Department4,
C.City City10,
C.STATE State11,
C.StartDate StartDate12,
C.Deadline Deadline13,
B.ID Table_B_ID,
A.Id Table_A_ID
FROM dbo.Table_A A
INNER JOIN dbo.Table_B B ON A.id = B.Table_A_Id
INNER JOIN dbo.Table_C C ON C.Table_B_Id = B.Id
新表:
CREATE TABLE [dbo].[Table_D] (
[Id] [int] IDENTITY (1, 1) PRIMARY KEY NOT NULL,
[ModelName] [varchar](max) NOT NULL,
[Table_C_Id] [int] NOT NULL,
[AttributeValue] [varchar](max) NOT NULL,
[CreatedDate] [datetime] NOT NULL,
[UpdatedDate] [datetime] NOT NULL,
CONSTRAINT FK_Table_C_Id FOREIGN KEY (Table_C_Id) REFERENCES some_schema.dbo.[Table_C] (Id)
ON DELETE CASCADE
ON UPDATE CASCADE
)
新表中的数据:
我只想在 select * from [dbo].[MySelectionInfo]
结果集中包含一些 ModelName 列值作为列名和 AttributeValue 作为值:
我可以使用PIVOT
函数达到预期的效果:
CREATE OR ALTER VIEW [dbo].[MySelectionInfo]
WITH schemabinding
AS
SELECT C.Id id0,
C.Code Code1,
C.Name Name2,
C.StartDate StartDate12,
C.Deadline Deadline13,
B.ID Table_B_ID,
A.Id Table_A_ID
FROM dbo.Table_A A
INNER JOIN dbo.Table_B B ON A.id = B.Table_A_Id
INNER JOIN dbo.Table_C C ON C.Table_B_Id = B.Id
LEFT JOIN (SELECT PivotTable.Table_C_Id,
PivotTable.attribute1,
PivotTable.attribute2,
PivotTable.attribute3
FROM (SELECT Table_D.Table_C_Id,
Table_D.ModelName,
Table_D.AttributeValue
FROM dbo.Table_C
INNER JOIN dbo.Table_D
ON Table_C.Id = Table_D.Table_C_Id) AS sourceTable
PIVOT (
Max(AttributeValue) FOR ModelName IN (attribute1, attribute2, attribute3)
) AS PivotTable) dbo.Table_D D ON D.Table_C_Id = C.Id
但是,运行上面的SQL语句后,我无法为视图创建聚集索引,因为LEFT
JOIN
,PIVOT
,MAX
被禁止在indexed views 中使用。
问题:是否有任何其他解决方案可以实现预期结果并且仍然将现有视图作为索引视图?
【问题讨论】:
您可以保留现有的索引视图并将LEFT JOIN
和PIVOT
添加到使用索引视图(可以封装在常规视图中)的查询中。
@DanGuzman,感谢您的回复。我不确定我是否完全理解你。根据 MS SQL 文档,我无法从索引视图中引用其他视图。你能提供一些样品吗?谢谢。
简短回答 - 不。但是您最初的观点相当直截了当,我不得不首先质疑索引它的效用。既然您现在选择了 EAV 方法,那么您应该真正研究这种选择,并了解从此时起您将承受的痛苦,试图将其转化为可用和可查询的信息。
@I.Domshchikov,正确的。如您所知,索引视图有很多限制,因此许多不允许的构造是行不通的。但是您仍然可以利用查询中现有索引视图的具体化带来的性能优势。
@I.Domshchikov,查看实际计划以确定是否/如何使用索引视图,并考虑连接表上的索引。您可能需要添加 NOEXPAND
提示才能使用索引视图。
【参考方案1】:
如果您的数据允许,您可以使用 case 语句而不是 PIVOTing 交叉表:
/*
drop view dbo.mytestinfoview;
go
drop table dbo.Table1;
go
--*/
create table dbo.Table1
(
id int,
ModelName varchar(20),
AttributeValue int
);
insert into dbo.Table1(id, ModelName, AttributeValue)
select distinct o.object_id, concat('attribute', v.id), o.attributevalue
from
(
select
object_id ,
abs(checksum(newid())) % 2 as attributevalue
from sys.objects
) as o
cross apply (values(1), (2), (3), (4)) as v(id)
go
create or alter view dbo.mytestinfoview
with schemabinding
as
select id, count_big(*) as thecounter,
sum(isnull(case ModelName when 'attribute1' then AttributeValue end, 0)) as attribute1,
sum(isnull(case ModelName when 'attribute2' then AttributeValue else 0 end, 0)) as attribute2,
sum(isnull(case ModelName when 'attribute3' then AttributeValue else 0 end, 0)) as attribute3
from dbo.Table1
group by id
go
create unique clustered index idx_v1 on dbo.mytestinfoview(id);
go
select * from dbo.mytestinfoview;
go
【讨论】:
以上是关于MS SQL:通过包含新表中的其他列来更改索引视图的主要内容,如果未能解决你的问题,请参考以下文章
(Sqlserver)将在查询结果插入新表中的时候添加一个自动增长列么 SQL语句怎么写