2009-10-25 71 views
5

我在開發新軟件時對現有數據庫進行了更改。也有相當多的傳統軟件的使用,需要繼續使用的數據庫,也就是我想保持現有的數據庫表,特效等INSTEAD OF UPDATE觸發器和更新主鍵

目前,我有表

 
CREATE TABLE dbo.t_station (
    tx_station_id  VARCHAR(4) NOT NULL, 
    tx_description  NVARCHAR(max) NOT NULL, 
    tx_station_type  CHAR(1)  NOT NULL, 
    tx_current_order_num VARCHAR(20) NOT NULL, 

    PRIMARY KEY (tx_station_id) 
) 

我需要在此表中包含一個引用Plant(生產設施)的新字段,並將tx_current_order_num移動到另一個表,因爲它不是所有行都需要的。所以我創建新表: -

 
CREATE TABLE Private.Plant (
    PlantCode INT   NOT NULL, 
    Description NVARCHAR(max) NOT NULL, 

    PRIMARY KEY (PlantCode) 
) 
CREATE TABLE Private.Station (
    StationId VARCHAR(4) NOT NULL, 
    Description NVARCHAR(max) NOT NULL, 
    StationType CHAR(1)  NOT NULL, 
    PlantCode INT   NOT NULL, 

    PRIMARY KEY (StationId), 

    FOREIGN KEY (PlantCode) REFERENCES Private.Plant (PlantCode) 
) 
CREATE TABLE Private.StationOrder (
    StationId VARCHAR(4) NOT NULL, 
    OrderNumber VARCHAR(20) NOT NULL, 

    PRIMARY KEY (StationId) 
) 

現在,我不希望有兩個地方相同的數據,所以我決定改變dbo.t_station錶轉成視圖,並提供觸發的,而不是來執行DELETE,INSERT和UPDATE。沒問題,我有[大部分]他們工作。

我的問題是INSTEAD OF UPDATE觸發器,更新主鍵列(tx_station_id)並更新到多行。

在觸發塊內部,有沒有辦法加入插入和刪除的[psuedo]表,以便我知道「更新前的主鍵」和「更新後的主鍵」?事情是這樣的......

 
UPDATE sta 
    SET sta.StationId = ins.tx_station_id 
    FROM Private.Station AS sta 
     INNER JOIN deleted AS del 
      INNER JOIN inserted AS ins 
       ON ROW_IDENTITY_OF(del) = ROW_IDENTITY_OF(ins) 
      ON del.tx_station_id = sta.StationId 

在這個階段,我已經把在觸發塊回滾更新檢查,如果主鍵列被更新,有不止一個行中插入或刪除,表。

+1

我曾希望有人可能有更好的答案!這個問題也讓我過去煩惱了。 – 2009-10-26 02:04:01

回答

3

簡短的回答是否定的。

可能在Private.Station上放置了一個代理鍵,並通過該視圖公開該代理鍵,並使用該鍵來識別值前後的值。您不需要更改主鍵或外鍵關係,但必須在視圖中公開一些不可更新的cruft,以便它顯示在僞表中。例如:

alter table Private.Station add StationSk int identity(1,1) not null 

注意,如果它使用SELECT *,這可能會破壞遺留應用程序。不過,沒有顯式插入列表的INSERT語句應該沒問題。

的短,有可能 inserted和deleted,使得ROW_NUMBER()OVER(ORDER BY NULLIF(的stationID,的stationID))將讓你加入這兩個之間的一些無證&一致的排序,但我非常猶豫走上路。非常非常猶豫。

你有意不啓用級聯更新嗎?當主鍵值可以更新時,它們很有用。例如:

CREATE TABLE Private.Station (
    StationId VARCHAR(4) NOT NULL, 
    Description NVARCHAR(max) NOT NULL, 
    StationType CHAR(1)  NOT NULL, 
    PlantCode INT   NOT NULL, 
    PRIMARY KEY (StationId), 
    FOREIGN KEY (PlantCode) REFERENCES Private.Plant (PlantCode) 
     ON UPDATE CASCADE 
     -- maybe this too: 
     -- ON DELETE CASCADE 
) 

有人可能會有更好的把戲。等着看!

+0

是的,考慮了代理關鍵思想,但我想保留表名和列。至於級聯更新和刪除不適合我主要關心的問題。站點ID在整個數據庫中被引用,我想確保引用表繼續引用正確的邏輯站。 – Kepboy 2009-10-25 23:56:51

+0

我應該指出,我並不完全不滿意我的單行解決方案,只是想我會問,因爲我喜歡瞭解這些東西。 – Kepboy 2009-10-25 23:57:30

+0

當前模式允許更新t_station.tx_station_id嗎?如果沒有,則使用COLUMNS_UPDATED()測試更新,如果檢測到任何更改,則回滾並引發錯誤。 – 2009-10-26 00:38:04

相關問題