INSTEAD OF UPDATE触发并更新主键

Kep*_*boy 5 t-sql sql-server sql-server-2005

我正在开发新软件时对现有数据库进行更改.还有很多遗留软件使用需要继续工作的数据库,即我想维护现有的数据库表,过程等.

目前我有桌子

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

我需要在此表中包含一个引用工厂(生产工具)的新字段,并将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

在这个阶段,我已经检查了触发器块,如果主键列已更新并且插入或删除的表中有多行,则会回滚更新.

Pet*_*hia 3

最简洁的答案是不。

可以在 Private.Station 上放置一个代理键,并通过视图公开它,并使用它来识别之前和之后的值。您不需要更改主键或外键关系,但您必须通过视图公开一些不可更新的内容,以便它显示在伪表中。例如:

alter table Private.Station add StationSk int identity(1,1) not null
Run Code Online (Sandbox Code Playgroud)

请注意,如果旧应用程序使用 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
)
Run Code Online (Sandbox Code Playgroud)

有人可能有更好的技巧。等等看!