2012-05-04 29 views
-1

在我的应用程序中,我使用触发器来计算成本并在插入数据时更新成本,但如果在帐单中插入200个项目,则需要2-3分钟来保存。但是如果我删除了触发它只需要不到30秒执行触发器时数据插入太慢

是否可以在不影响应用程序的情况下相互依赖地执行触发器? OR 是否有任何替代办法做到这些?(要带只比30年代少,但成本更新用应该相互依赖工作)

我可以使用线程/ BackgroundWorker的?难道是挂起应用程序时,10个用户做在连续计费一时间

这些是我的触发

SET NOCOUNT ON; 
declare @nopqty decimal(10,2) 
declare @nminusqty decimal(10,2) 
declare @ntotamt decimal(10,2) 
declare @nstock decimal(10,2) 
declare @ncost decimal(10,2) 
declare @qry nvarchar(4000) 
declare @norgcd int 
declare @npartno nvarchar(20) 
set @norgcd = (select orgcd from inserted) 
set @npartno = (select docpart from inserted) 
set @nopqty=(select oqty101 from stock where [email protected]) 
set @ntotamt=(select ocost101 from stock where [email protected]) 
set @nopqty = @nopqty+ (select sum(sellqty) from prtdet where trcd in(select trcd from invtran where qtyadd='+' and lcardx='True') and [email protected] and status1='True' and status2='True' and status3='True' and [email protected]) 
set @nminusqty = (select sum(sellqty) from prtdet where trcd in(select trcd from invtran where qtyadd='-' and lcardx='True') and [email protected] and status1='True' and status2='True' and status3='True' and [email protected]) 
set @ntotamt = @ntotamt+ (select sum(tamt) from prtdet where trcd in(select trcd from invtran where qtyadd='+' and lcardx='True') and [email protected] and status1='True' and status2='True' and status3='True' and [email protected]) 
set @nstock =(@[email protected]) 
set @ncost =(@ntotamt/@nopqty) 
set @qry = 'update stock set cqty'+convert(varchar(3),@norgcd)+'='+convert(nvarchar(12),@nstock)+',ccost'+convert(varchar(3),@norgcd)+'='+convert(nvarchar(12),@ncost)+' where part='''[email protected]+'''' 
exec sp_executesql @qry 

我是在触发小清新和存储过程

我想更新库存成本和stockvalue(加权平均)用于每个更新和项目的插入。任何人都可以告诉我很好的方法来实现这些

+0

您可以在插入记录时添加更多关于触发器实际执行的信息吗?您是一次插入1行还是批量执行此操作?如果您一次只做1行,您可能会遇到延迟/往返问题。除非使用事务来锁定表,否则可以使用backgroundworker。如果您正在使用交易,其他9个用户将无法修改,直到完成第一个交易。 –

+1

我会更感兴趣的是为什么它需要30秒才能在您的良好场景中插入200件物品。 –

+1

触发器可以很好,这取决于你如何编码它。如果你在触发器中有一个游标或一个循环,你需要重写它以使用基于集合的操作,如果你想要任何体面的表现。 –

回答

0

我发现的一件事是,如果您使用触发器更新基于表中所有其他行的特定字段,创建一个可能是个好主意计算列,它使用UDF作为其值而不是触发器。这有几个好处:

  1. 插入/删除要快得多,因为现在您不必在插入/删除时重新计算值。删除触发器对于字段设置值要昂贵得多,因为现在您必须修改所有其他行的所有字段。
  2. 如果此列有索引,那么在插入/删除时重建索引会导致额外的开销。但是,只是需要警告的是,您不能索引非确定性计算列(意思是根据输入返回不同的值)。

最终,它只是取决于触发器在做什么。如果触发器必须从其他表中获取更多信息来更新价格,那么UDF可能是最佳选择。另一方面,如果还有其他相关的逻辑,那么我们真的不能帮助你理解为什么没有真正理解触发器的作用。

编辑:好的,我注意到你的SQL代码,实际上花时间来辨别你正在尝试做什么。我可能建议重构原始查询以使其更快?

SELECT @norgcd = orgcd, @npartno FROM inserted 
SELECT @nopqty=oqty101, @ntotamt= ocost101 FROM stock WHERE [email protected] 
SELECT 
    @nopqty = @nopqty + SUM(CASE WHEN b.qtyadd = '+' THEN a.sellqty ELSE 0 END), 
    @nminusqty = SUM(CASE WHEN b.qtyadd = '-' THEN a.sellqty ELSE 0 END), 
    @ntotamt = @ntotamt + SUM(CASE WHEN b.qtyadd = '+' THEN a.tamtELSE 0 END) 
FROM 
    prtdet a 
    JOIN (SELECT DISTINCT trcd, qtyadd FROM invtran WHERE lcardx='True') b ON a.trcd = b.trcd 
WHERE 
    [email protected] 
    AND a.status1='True' 
    AND a.status2='True' 
    AND a.status3='True' 
    AND [email protected] 

SET @nstock =(@[email protected]) 
SET @ncost =(@ntotamt/@nopqty) 
SET @qry = 'update stock set cqty'+convert(varchar(3),@norgcd)+'='+convert(nvarchar(12),@nstock)+',ccost'+convert(varchar(3),@norgcd)+'='+convert(nvarchar(12),@ncost)+' where part='''[email protected]+'''' 

至于重构实际的更新查询,抱歉,但你必须自己做。由于您试图使用“动态”SQL来做到这一点,因此您将不得不承受最大的陷阱:由于动态性过高而导致不必要的查询。我的建议?该更新触发器在代码中的单独查询(不是SQL查询)要好得多,但如果在插入/更新过程中出现问题,则所有更新触发器都以相同的事务执行,但实际上并未执行更新。无可否认,由于您必须处理单个记录,所以速度较慢,但​​同样,在使用动态SQL技术时这是一种折衷。

+0

好主意创建一个计算列,使用UDF它的值而不是它在新条目中为我工作的触发器。 – dfgv

+0

但是当我想计算旧账单的加权平均数(平均成本为开票日期)这些方法不会工作 – dfgv

+0

不知道还有什么要告诉你,因为你不会告诉我们你的信息是什么,重新努力实现。所以计算列不会减慢插入速度,因为它现在跳过触发器,GREAT。这是解决的一个问题。如果你仍然有这个问题,那么也许你应该看看为什么它会变得很慢,而不是找出如何修复它(10次中有9次会帮助处理SQL数据库) – SPFiredrake