Sql server 而不是更新触发器和更新主键

Sql server 而不是更新触发器和更新主键,sql-server,sql-server-2005,tsql,Sql Server,Sql Server 2005,Tsql,我在开发新软件时对现有数据库进行更改。还有相当多的遗留软件使用需要继续工作的数据库,即我希望维护现有的数据库表、进程等 现在我有桌子了 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

我在开发新软件时对现有数据库进行更改。还有相当多的遗留软件使用需要继续工作的数据库,即我希望维护现有的数据库表、进程等

现在我有桌子了

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) ) 创建表dbo.t_站( tx_station_id VARCHAR(4)不为空, tx_说明NVARCHAR(最大值)不为空, tx_站_类型字符(1)不为空, tx\u当前\u顺序\u num VARCHAR(20)不为空, 主键(发送站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) ) 创建表Private.Plant( PlantCode INT不为空, 说明NVARCHAR(最大值)不为空, 主键(PlantCode) ) 创建表Private.Station( StationId VARCHAR(4)不为空, 说明NVARCHAR(最大值)不为空, StationType字符(1)不为空, PlantCode INT不为空, 主键(StationId), 外键(PlantCode)引用Private.Plant(PlantCode) ) 创建表Private.StationOrder( StationId VARCHAR(4)不为空, OrderNumber VARCHAR(20)不为空, 主键(StationId) ) 现在,我不想在两个地方有相同的数据,所以我决定将dbo.t_station表更改为视图,并提供替代触发器来执行删除、插入和更新。没问题,我让[大部分]人都在工作

我的问题是关于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 更新sta 设置sta.StationId=ins.tx\U站\U id 从私人车站出发,作为sta 内部联接已作为del删除 内部联接作为ins插入 在(del)的行上=在(ins)的行上 在del.tx\u站上\u id=sta.StationId
在这个阶段,我在触发器块中做了一个检查,如果主键列被更新,并且插入或删除的表中有多行,则会回滚更新。

简短的回答是否

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

alter table Private.Station add StationSk int identity(1,1) not null
注意,如果使用SELECT*,这可能会破坏旧应用程序。但是,没有显式INSERT列列表的INSERT语句应该可以

除此之外,插入和删除之间可能存在一些未记录且一致的顺序,因此(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
)

有人可能有更好的把戏。等等看

是的,考虑过代理键的想法,但我想保留表名和列。至于级联更新和删除,这对我的主要关注点不起作用。StationId在整个数据库中都被引用,我想确保引用表继续引用正确的、逻辑的station。我应该指出,我并不是完全不满意我的单行解决方案,我只是想问一下,因为我想知道这些事情。当前模式中是否允许更新t_station.tx_station_id?如果没有,请使用列_UPDATED()测试更新,如果检测到任何更改,请回滚并引发错误。我本来希望有人能给出更好的答案!这个问题过去也曾困扰过我。