【发布时间】:2014-07-05 20:29:51
【问题描述】:
我遇到了一个奇怪的情况,表上的更新触发器没有更新依赖于其他列的列,这些列也在更新期间得到更新。这是复制此问题的背景和代码。
我有一个商品管理应用程序,可以每天跟踪水果价格。我需要每天计算水果的价格和数量趋势。每日水果价格和价格量计算存储在 FruitTrades 表中。我在这个表上定义了一个更新触发器,每当在这个表中插入或更新一行时,它将计算价格和交易量趋势。
每日水果价格和数量以一个平面文件的形式提供给我,我将其导入一个名为 PriceData 的简单表中。然后我使用一个简单的 INSERT 语句将价格和交易量信息从该表移至 FruitTrades 表。这会触发 FruitTrades 中的更新触发器,但触发器不会更新其中的两列。知道为什么吗?
复制此问题的步骤如下:
-- 步骤 1(创建 FruitTrades 表)
CREATE TABLE [dbo].[FruitTrades](
[FID] [nchar](3) NOT NULL,
[TradeDate] [smalldatetime] NOT NULL,
[TAID] [tinyint] NULL,
[Price] [real] NOT NULL,
[Vol] [int] NULL,
[3DAvgPrice] [real] NULL,
[5DAvgPrice] [real] NULL,
[VolTrend] [real] NULL,
[VolTrendPrevD] [real] NULL,
CONSTRAINT [PK_FruitTrades] PRIMARY KEY CLUSTERED
(
[FID] ASC,
[TradeDate] DESC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
) ON [PRIMARY];
-- 步骤 2(创建更新触发器)
CREATE TRIGGER [dbo].[TRG_FruitTrades_Analysis]
ON [dbo].[FruitTrades]
AFTER INSERT, UPDATE
AS
BEGIN
-- SET NOCOUNT ON added to prevent extra result sets from
-- interfering with SELECT statements.
SET NOCOUNT ON;
UPDATE FruitTrades SET
-- Calculate the 3 day average price
[FruitTrades].[3DAvgPrice] =
(
SELECT AVG(Price) FROM
(
SELECT TOP 3 Price FROM FruitTrades
WHERE FID = [Inserted].[FID] AND TradeDate <= [Inserted].[TradeDate]
) AS Last3Trades
),
-- Calculate the 5 day average price
[FruitTrades].[5DAvgPrice] =
(
SELECT AVG(Price) FROM
(
SELECT TOP 5 Price FROM FruitTrades
WHERE FID = [Inserted].[FID] AND TradeDate <= [Inserted].[TradeDate]
) AS Last5Trades
),
-- Fetch the previous days VolTrend and update VolTrendPrev column
[FruitTrades].[VolTrendPrevD] =
(
SELECT TOP 1 VolTrend FROM FruitTrades
WHERE FID = [Inserted].[FID] AND TradeDate < [Inserted].[TradeDate]
),
-- Calculate Volume Trend and update VolTrend column
[FruitTrades].[VolTrend] =
(
ISNULL([FruitTrades].[VolTrendPrevD], 0) +
([Inserted].[Vol] * (([Inserted].[Price] /
(SELECT TOP 1 Price FROM FruitTrades WHERE FID = [Inserted].[FID] AND TradeDate < [Inserted].[TradeDate])) - 1.0 ))
),
-- Now Update the Action ID column
[FruitTrades].[TAID] =
(
CASE
WHEN [FruitTrades].[3DAvgPrice] >= [FruitTrades].[5DAvgPrice] AND [FruitTrades].[VolTrend] >= [FruitTrades].[VolTrendPrevD] THEN 1
WHEN [FruitTrades].[3DAvgPrice] >= [FruitTrades].[5DAvgPrice] AND [FruitTrades].[VolTrend] <= [FruitTrades].[VolTrendPrevD] THEN 2
WHEN [FruitTrades].[3DAvgPrice] <= [FruitTrades].[5DAvgPrice] AND [FruitTrades].[VolTrend] >= [FruitTrades].[VolTrendPrevD] THEN 3
WHEN [FruitTrades].[3DAvgPrice] <= [FruitTrades].[5DAvgPrice] AND [FruitTrades].[VolTrend] <= [FruitTrades].[VolTrendPrevD] THEN 4
ELSE NULL
END
)
FROM FruitTrades
INNER JOIN Inserted ON Inserted.FID = FruitTrades.FID AND Inserted.TradeDate = FruitTrades.TradeDate
END
-- 步骤 3(创建 PriceData 表)
CREATE TABLE [dbo].[PriceData](
[FID] [nchar](3) NOT NULL,
[TradeDate] [smalldatetime] NOT NULL,
[Price] [real] NULL,
[Vol] [real] NULL,
CONSTRAINT [PK_PriceData] PRIMARY KEY CLUSTERED
(
[FID] ASC,
[TradeDate] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
) ON [PRIMARY]
-- STEP 4(模拟数据导入 PriceData 表)
INSERT INTO PriceData (FID, TradeDate, Price, Vol) VALUES ('APL', '4/30/2012', 200, 1000);
INSERT INTO PriceData (FID, TradeDate, Price, Vol) VALUES ('APL', '4/29/2012', 190, 1200);
INSERT INTO PriceData (FID, TradeDate, Price, Vol) VALUES ('APL', '4/28/2012', 195, 1250);
INSERT INTO PriceData (FID, TradeDate, Price, Vol) VALUES ('APL', '4/27/2012', 205, 1950);
INSERT INTO PriceData (FID, TradeDate, Price, Vol) VALUES ('APL', '4/26/2012', 200, 2000);
INSERT INTO PriceData (FID, TradeDate, Price, Vol) VALUES ('APL', '4/25/2012', 180, 1300);
INSERT INTO PriceData (FID, TradeDate, Price, Vol) VALUES ('APL', '4/24/2012', 185, 1250);
-- STEP 5(将价格波动日期从 PriceDate 表移动到 Fruit Tables)
INSERT INTO FruitTrades (FID, TradeDate, Price, Vol) SELECT FID, TradeDate, Price, Vol FROM PriceData;
-- 第 6 步(检查 FruitTrades 表的正确性)
SELECT * FROM FruitTrades ORDER BY TradeDate
--- 结果
在第 6 步之后,您会发现 FruitTrades 表列中的 TAID 和 VolTrendPrevD 仍然为 NULL。
非常感谢任何有关如何解决此问题的帮助。
【问题讨论】:
-
为什么要使用触发器?更糟糕的仍然是按记录计算聚合的触发器。鉴于我每天都有一份文件,我刚刚写了一个处理它的过程。至少那时我可以分解它并测试每个部分,看看它是否符合我的预期。
-
可能。我确实想到了一个开始的过程。但是触发器方法似乎更简单,并且需要的代码也更少。我只是想了解为什么它不起作用?例如,是否涉及种族问题?
标签: sql-server-2005 triggers calculated-columns