2009-10-25 51 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

相关问题