2013-01-24 88 views
0

我正在將我的數據庫從太平洋時間的存儲日期時間過渡到UTC,但不會同時更改所有代碼。SQL觸發器觸發但未插入原始值

我想寫一個觸發器,將更新在任一列中輸入的時間,並將它們轉換並插入到另一列中。

Ex。如果我在OriginalTime列中插入太平洋時間,它應該將時間轉換爲UTC並使用UTC時間更新NewTime列。相反,如果我在NewTime中插入/更新值,它應該將時間轉換回太平洋並將其放入OriginalTime。

我是否錯誤地循環了某些東西?

ALTER TRIGGER tr_Calls_CreateDate ON Calls 
AFTER INSERT, UPDATE 
AS 
BEGIN 
SET NOCOUNT ON 

DECLARE 
    @CallId INT, 
    @CreateDate DATETIME, 
    @CreateDateUTC DATETIME 

--Create cursor 
DECLARE CreateDate_Cursor CURSOR LOCAL FOR 
    SELECT CallId, CreateDate, CreateDateUTC FROM Inserted 

OPEN CreateDate_Cursor; 

-- Get First Row 
FETCH NEXT FROM CreateDate_Cursor INTO @CallId, @CreateDate, @CreateDateUTC; 

WHILE @@FETCH_STATUS = 0 
BEGIN 
    IF UPDATE ([CreateDate]) 
    BEGIN 
     UPDATE Calls 
     SET CreateDateUTC = dbo.ConvertPacificTimeToUTC(@CreateDate) 
     WHERE CallId = @CallId 
    END 

    IF UPDATE ([CreateDateUTC]) 
    BEGIN 
     UPDATE Calls 
     SET CreateDate = dbo.ConvertUTCTimeToPacific(@CreateDateUTC) 
     WHERE CallId = @CallId 
    END 

    FETCH NEXT FROM CreateDate_Cursor INTO @CallId, @CreateDate, @CreateDateUTC; 
END 

-- Free Up Cursor 
CLOSE CreateDate_Cursor; 
DEALLOCATE CreateDate_Cursor; 
END 

由於某種原因,我當前的觸發器正確輸入轉換後的值,但導致觸發器觸發的插入似乎失敗。

如果我插入值:

INSERT INTO Calls (CreateDate) 
VALUES (GETDATE()) -- getdate currently outputs in pacific time 

我得到的結果觸發而不是插入的值:

+-----------------+--------------------------+ 
| CreateDate |  CreateDateUTC  | 
+-----------------+--------------------------+ 
|  NULL  | 2013-01-24 20:27:13.510 | 
+-----------------+--------------------------+ 
+2

一個光標和一個觸發器......我的眼睛,我的眼睛......他們燃燒。我試圖用單個更新和一個case語句來重寫它,使其基於set。 – RThomas

+0

哈哈我已經看到了很多情緒,但沒有太多的支持。 (並不是說沒有)因爲每次添加/修改記錄時都需要觸發,是不是合適的觸發器?就遊標/集合辯論而言,你是否有任何資源方便地顯示如何將其轉換爲基於集合的模型? – jstim

回答

5

在插入UPDATE(column)是所有列真。那就是你的第二次更新在CreateDate列中寫入一個空值。

因此,您需要創建兩個觸發器,一個處理代碼中的更新,另一個處理插入。如果只有CreateDate被賦值,CreateDateUTC是NULL,你可以檢查它。

此外,你應該真的不使用遊標。使用這樣的事情,而不是:

UPDATE c SET 
    CreateDate = ISNULL(CreateDate, dbo.ConvertUTCTimeToPacific(i.CreateDateUTC)), 
    CreateDateUTC = ISNULL(CreateDateUTC, dbo.ConvertPacificTimeToUTC(i.CreateDate)) 
FROM dbo.Calls AS c 
JOIN INSERTED AS i 
ON i.CallId = c.CallId; 

也就是說,對於INSERT觸發器。對於更新,可以使用這樣的事情:

UPDATE c SET 
    CreateDate = CASE WHEN UPDATE ([CreateDateUTC]) THEN CreateDate 
        ELSE dbo.ConvertUTCTimeToPacific(i.CreateDateUTC) 
       END, 
    CreateDateUTC = CASE WHEN UPDATE ([CreateDate]) THEN CreateDateUTC 
        ELSE dbo.ConvertPacificTimeToUTC(i.CreateDate) 
        END 
FROM dbo.Calls AS c 
JOIN INSERTED AS i 
ON i.CallId = c.CallId; 

這是所有未經測試的代碼,但它應該工作。


編輯:見我不再爲什麼你真的應該換這UPDATEIF聲明的內部下面的評論。

+0

嘿,我想我幾周前在紅門SQLInTheCity西雅圖見到你。如果那是你,好的介紹。答案+1。 – RThomas

+0

塞巴斯蒂安,謝謝你的回答。 INSERT看起來正確,但是我對UPDATE有個疑問。我認爲邏輯稍微落後,但我不想在沒有討論的情況下編輯帖子。我用反向邏輯做了一個要點,還有一個關於是否需要CASE陳述的問題。感謝您的輸入。 https://gist.github.com/4629551 – jstim

+0

@RThomas,我確實在場。很開心你喜歡。 –