2014-05-17 2 views
0

테이블의 업데이트 트리거가 업데이트 중에 업데이트되는 다른 열에 종속적 인 열을 업데이트하지 않는 이상한 상황이 발생했습니다. 이 문제를 복제하기위한 배경과 코드는 다음과 같습니다.종속 열에 대해 SQL Server 2005 업데이트 트리거가 작동하지 않습니다.

매일 과일 가격을 추적하는 상품 관리 애플리케이션이 있습니다. 매일 과일에 대한 가격 및 수량 추세를 계산할 필요가 있습니다. 매일 과일 가격과 가격 계산은 FruitTrades 테이블에 저장됩니다. 이 테이블에 행이 삽입되거나 업데이트 될 때마다 가격 및 볼륨 추세를 계산하는이 테이블에 대해 업데이트 트리거를 정의했습니다.

PriceData라는 간단한 테이블로 가져 오는 플랫 파일로 매일 과일 가격과 볼륨이 표시됩니다. 그런 다음 간단한 INSERT 문을 사용하여이 테이블의 Price 및 Volume 정보를 FruitTrades 테이블로 이동합니다. 이것은 FruitTrades에서 업데이트 트리거를 시작하지만 열 두 개가 트리거에 의해 업데이트되지 않습니다. 왜 그런가? 다음과 같이이 문제를 복제하기위한

단계는 다음과 같습니다

- 2 단계 (업데이트 트리거 만들기)

- 1 단계

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]; 

합니다 (FruitTrades 테이블을 생성)

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); 

시뮬레이션 - 과일 테이블에 PriceDate 테이블 STEP 5 (이동 가격 부피 일자)

INSERT INTO FruitTrades (FID, TradeDate, Price, Vol) SELECT FID, TradeDate, Price, Vol FROM PriceData; 

- 6 단계합니다 (FruitTr을 확인 정확성에 대한 ADES 테이블)

SELECT * FROM FruitTrades ORDER BY TradeDate 

는 --- 6 단계 후

결과는 당신이 FruitTrades 테이블 컬럼의 TAID 및 VolTrendPrevD이 NULL 남아 있습니다.

이 문제를 해결하는 방법에 대한 도움을 주실 수 있습니다.

+0

왜 당신이 사용하는 트리거? 레코드 기반으로 레코드 단위로 집계를 계산하는 여전히 나쁜 트리거. 내가 매일 파일을 얻는다면, 나는 그것을 처리 할 프로세스를 썼을 것입니다. 적어도 나는 그것을 분쇄하고 그것이 내가 기대했던 한 경우에 볼 수있는 각 부분을 테스트 할 수 있었다. –

+0

가능합니다. 나는 시작하는 과정을 생각했다. 그러나 트리거 접근 방식은 단순 해 보였고 코드도 적게 필요했습니다. 왜 작동하지 않는지 이해하고 싶습니다. 예를 들어 인종 문제가 관련되어 있습니까? – explorer

답변

0

이 문제로 5 일 동안 일하고 인터넷 검색을 한 끝에 드디어 해결책을 찾았습니다.

첫 번째 문제는 트리거에 대한 나의 이해 부족과 발사 방법 때문이었습니다.SQL 설명서에 따라,

SQL Server는이 때문에 설계 원칙에 영향을 행

당 한번도 문 당 한 번만 불을 트리거 5 단계에서, 나는에서 대량 삽입을 수행 할 때 FruitTrades 테이블에 PriceData 테이블, 트리거는 각 행에 대해 대신에 한 번, 한 번만 발생합니다. 따라서 업데이트 된 값이 올바르지 않습니다.

VolTrendPrevD는 업데이트 트리거의 Select 문이 FruitTrades 테이블의 첫 번째 행과 항상 일치하므로 (Inserted 테이블에 여러 행이 있기 때문에) null로 유지되며이 행에 대해 VolTrend는 null입니다. VolTrendPrevD가 null 때문에

TAID가 null 남아있다.

이제 수정 :

  1. 가져 오기 MSACCESS 테이블에 가격 데이터가 포함 된 텍스트 파일. 링크 된 테이블을 사용하여 SQL Server 테이블에 대량 삽입을 수행합니다. 이 방법은 ODBC를 사용하여 대량 삽입을 여러 개의 단일 삽입으로 변환하므로 첫 번째 문제점을 우회합니다.

  2. 은 계산 열로 변환 VolTrend. 따라서 트리거에서 업데이트 할 필요가 없습니다.

  3. FruitTrades 테이블에 추가 PricePrevD 열을 도입하고 VolTrendPrevD 열과 같은 방식으로 트리거의 해당 값을 업데이트하십시오.

  4. 는 가장 중요한 (Access에서 해당 날짜의 인덱스를 생성하여) 액세스로부터 삽입 행 날짜 오름차순으로 삽입되도록. 그렇지 않으면 원하는 결과가 누락됩니다. 이 도움이

희망 ... :-)

+0

항상 여러 행을 처리하기 위해 트리거를 쓰기 –