SQL脚本花费了太多时间并抛出了超时错误

时间:2015-06-30 11:28:05

标签: sql sql-server-2008 stored-procedures

我正从我的应用程序执行SQL脚本。使用此脚本,我从Product表中获取数据并将其放入Table1。如果我直接从SSMS执行此脚本,则需要00:01:27分钟。但是使用应用程序会给我一个错误:超时已过期。操作完成之前经过的超时时间或服务器没有响应。

这是我的剧本:

-- Deleting [Table1] table if exists before creating because we don't need to keep track of records
IF EXISTS (SELECT * FROM sys.objects WHERE object_id = OBJECT_ID(N'Table1'))
BEGIN
    DROP TABLE [dbo].[Table1]
END

-- Creating [Table1] table
CREATE TABLE [dbo].[Table1] 
(
    [Id] [int] IDENTITY(1,1) NOT NULL,
    [ProductId] [int] NOT NULL,
    [MyStatus] [bit] NOT NULL,
    [IsDeleted] [bit] NOT NULL,
    [InTime] [datetime] NULL,
    [StoreId] [int] NOT NULL,
    [LanguageId] [int] NOT NULL,

    PRIMARY KEY([Id])
);

DECLARE @pId int
DECLARE @sId int

Truncate Table [dbo].[Table1]

Insert Into [dbo].[Table1] (ProductId, MyStatus, IsDeleted, InTime, StoreId, LanguageId)
   select distinct 
       p.Id, 1, 1, GETDATE(), s.Id, l.Id 
   from 
       [dbo].[Store] s, [dbo].[Product] p, [dbo].[Language] as l
   left join 
       [dbo].[StoreMapping] sm on sm.EntityId = l.Id 
   where 
       (l.LimitedToStores = 1 and s.Id in (sm.StoreId) 
        and sm.EntityName = 'Language') or l.LimitedToStores = 0 

DECLARE tempCursor CURSOR SCROLL FOR 
   select 
       p.Id, sm.StoreId 
   from 
       [dbo].[Product] as p
   join 
       [dbo].[StoreMapping] as sm on p.Id = sm.EntityId
   join 
       [dbo].[Store] as s on sm.StoreId=s.Id
   where 
       p.LimitedToStores = 1 and sm.EntityName = 'Product'

OPEN tempCursor 
FETCH FIRST FROM tempCursor INTO @pId, @sId

WHILE @@fetch_status = 0   
BEGIN    
    UPDATE [dbo].[Table1] 
    SET IsDeleted = 0
    WHERE ProductId = @pId AND StoreId = @sId

    FETCH NEXT FROM tempCursor INTO @pId, @sId;
END

CLOSE tempCursor

UPDATE [dbo].[Table1]
SET IsDeleted = 0
where ProductId in (Select p.Id 
                    from [dbo].[Product] as p 
                    where p.LimitedToStores = 0)

UPDATE [dbo].[Table1]
SET IsDeleted = 1
where ProductId in (Select p.Id 
                    from [dbo].[Product] as p 
                    where p.Published = 0 OR p.Deleted = 1 
                       OR p.VisibleIndividually = 0)

DEALLOCATE tempCursor

有人可以帮我改进这个脚本吗?

1 个答案:

答案 0 :(得分:3)

使用CURSOR并在表1中循环设置IsDeleted=0的部分可以替换为以下更新语句:

UPDATE
  [dbo].[Table1]
SET
  IsDeleted=0
FROM
  [dbo].[Product] AS p
  JOIN [dbo].[StoreMapping] AS sm ON p.Id=sm.EntityId
  JOIN [dbo].[Store] AS s ON sm.StoreId=s.Id
  JOIN [dbo].[Table1] AS t1 ON t1.ProductId=p.Id AND t1.StoreId=s.Id
WHERE
  p.LimitedToStores=1 AND
  sm.EntityName ='Product'

最后两个查询最好用JOIN编写

UPDATE
  [dbo].[Table1]
SET
  IsDeleted=0
FROM
  [dbo].[Table1] AS t1
  JOIN [dbo].[Product] AS p ON
    p.Id=t1.ProductId
WHERE
  p.LimitedToStores=0

UPDATE
  [dbo].[Table1]
SET
  IsDeleted=1
FROM
  [dbo].[Table1] AS t1
  JOIN [dbo].[Product] AS p ON
    p.Id=t1.ProductId
WHERE
  p.Published=0 OR 
  p.Deleted=1 OR 
  p.VisibleIndividually=0