2011-03-11 75 views
6

计算列我有这样的事情坚持用子查询

create function Answers_Index(@id int, @questionID int) 
returns int 
as begin 
    return (select count([ID]) from [Answers] where [ID] < @id and [ID_Question] = @questionID) 
end 
go 

create table Answers 
(
    [ID] int not null identity(1, 1), 
    [ID_Question] int not null, 
    [Text] nvarchar(100) not null, 
    [Index] as [dbo].[Answers_Index]([ID], [ID_Question]), 
) 
go 

insert into Answers ([ID_Question], [Text]) values 
    (1, '1: first'), 
    (2, '2: first'), 
    (1, '1: second'), 
    (2, '2: second'), 
    (2, '2: third') 

select * from [Answers] 

伟大的工程,但它往往查询速度下降了不少。我如何使列Index持续存在?我曾尝试以下操作:

create table Answers 
(
    [ID] int not null identity(1, 1), 
    [ID_Question] int not null, 
    [Text] nvarchar(100) not null, 
) 
go 

create function Answers_Index(@id int, @questionID int) 
returns int 
with schemabinding 
as begin 
    return (select count([ID]) from [dbo].[Answers] where [ID] < @id and [ID_Question] = @questionID) 
end 
go 

alter table Answers add [Index] as [dbo].[Answers_Index]([ID], [ID_Question]) persisted 
go 

insert into Answers ([ID_Question], [Text]) values 
    (1, '1: first'), 
    (2, '2: first'), 
    (1, '1: second'), 
    (2, '2: second'), 
    (2, '2: third') 

select * from [Answers] 

但是,这将引发以下错误:Computed column 'Index' in table 'Answers' cannot be persisted because the column does user or system data access.或者我应该忘掉它,使用[Index] int not null default(0)on insert触发补吗?

编辑:谢谢你,最终的解决方案:

create trigger [TRG_Answers_Insert] 
on [Answers] 
for insert, update 
as 
    update [Answers] set [Index] = (select count([ID]) from [Answers] where [ID] < a.[ID] and [ID_Question] = a.[ID_Question]) 
     from [Answers] a 
     inner join [inserted] i on a.ID = i.ID  
go 
+0

说实话,我不完全明白你正在试图解决什么? - 是选择查询慢不会触及你的“索引”列,所以我不认为这是相关的 - 尽管你可能想要添加一个或两个索引... – 2011-03-11 17:10:55

回答

4

您可以将列更改为普通列,然后在使用触发器插入/更新该行时更新其值。

create table Answers 
(
[ID] int not null identity(1, 1), 
[ID_Question] int not null, 
[Text] nvarchar(100) not null, 
[Index] Int null 
) 

CREATE TRIGGER trgAnswersIU 
ON Answers 
FOR INSERT,UPDATE 
AS 
    DECLARE @id int 
    DECLARE @questionID int 
    SELECT @id = inserted.ID, @questionID = inserted.ID_question 


    UPDATE Answer a 
    SET Index = (select count([ID]) from [Answers] where [ID] < @id and [ID_Question] = @questionID) 
    WHERE a.ID = @id AND a.ID_question = @questionID 

GO 

NB *这是完全不正确的,因为它不会在UPDATE正常工作,我们不会有“插入”表格来引用来获取ID和questionid。有解决的办法,但我不记得它现在:(

Checkout this for more info

+0

这不包含多行INSERT/UPDATE。 – 2015-02-12 11:56:03

0

计算列只存储来执行计算的公式。这就是为什么当从表中查询计算列时它会变慢。如果您想将值保存到实际的表列中,那么您使用触发器是正确的。

+3

持久计算列应该保存计算值(他们检测到需要更新被模式绑定)...问题是计算列的一般限制(对于持续计算的列,还有更多的限制) – 2011-04-19 06:28:17