我在开发新软件时对现有数据库进行了更改。还有很多遗留软件使用需要继续工作的数据库,即我想维护现有的数据库表,过程等。
目前我有桌子
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
在这个阶段,如果主键列已更新并且插入或删除的表中有多行,我会在触发器块中检查回滚更新。
答案 0 :(得分:3)
简短的回答是否定的。
您可以在Private.Station上放置代理键,并通过视图公开它,并使用它来识别值之前和之后。您不需要更改主键或外键关系,但是您必须通过视图公开一些不可更新的副本,以便它显示在伪表中。例如:
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
)
有人可能有更好的伎俩。等等看!