模式兼容性触发器



我觉得这个不错。首先,我真的不知道什么是触发器,现在可能很明显了。

触发器是否有利于维护数据库模式之间的向后兼容性?

假设我在版本1中有一个一对多的关系。在版本2中,这已更改为多对多。是否正确实现触发器能够处理这一点,以便允许两个版本在同一数据库上运行?这是个好主意吗?

实现向后兼容性从来都不是直截了当的。假设您有(版本1):

CREATE TABLE T1 (
    ID int not null primary key,
    ColA varchar(10) not null
)
CREATE TABLE T2 (
    ID int not null primary key,
    T1ID int not null,
    ColB varchar(10) not null,
    constraint FK_T2_T1 FOREIGN KEY (T1ID) references T1
)

,现在,对于版本2,您希望引入:

CREATE TABLE T1_T2 (
    T1ID int not null,
    T2ID int not null,
    constraint PK_T1_T2 PRIMARY KEY (T1,T2),
    constraint FK_T1_T2_T1 FOREIGN KEY (T1ID) references T1,
    constraint FK_T1_T2_T2 FOREIGN KEY (T2ID) references T2
)

而且,我从你的问题中想象,你认为T1_T2上的活动可以维持T2中现有的T1ID列,以实现向后兼容性。

这当然可能发生,但是你有一大堆问题要解决:

  • 如果T1_T2中有多行,您应该将哪个T1ID值写入T2 ?
  • 如果这行被删除,T2中的T1ID应该发生什么-设置NULL,选择另一个值?
  • 如果匹配T2ID的所有行从T1_T2中删除怎么办?应该删除T2中的行吗?是否将T1ID设置为NULL?
  • 如果版本1应用程序在T2中更新T1ID,并且在T1_T2中不存在行,这是一个错误还是应该插入新行?
  • 如果T2中的行没有特定的T1ID,那么版本1应用程序可能会假设它可以从T1中删除一行

我相信还有更多。您可以解决所有这些问题,但您永远无法完美地模拟版本1模式的100%使用的旧行为。


如果你能解决以上所有的问题,让你满意,那么是的,你可以使用触发器执行这些维护任务。正如我所说的那样,它不会是100%,所以您可能仍然需要调整版本1应用程序来解决他们的一些期望。

是的,您可以通过在旧版本的视图上使用一个INSTEAD OF触发器来插入、更新和删除。为了更清楚地说明这一点,让我们考虑以下示例:

v1:
    A(id int, data varchar(30))
    B(id int, a_id int, data varchar(30))
v2:
    A(id int, data varchar(30))
    B(id int, data varchar(30), data2 varchar(20))
    AB(a_id int, b_id int)

首先创建一个视图来模拟旧版本的B表。棘手的事情是决定将哪个AB关系显示给旧的应用程序。一种选择是将bit类型的primary_b列添加到AB表中。下面的视图使用了这个选项

CREATE VIEW OldB AS 
    SELECT B.id AS id, AB.a_id AS a_id, B.data AS data,  
    FROM B INNER JOIN AB ON B.id = AB.b_id
    WHERE AB.primary_b = 1

接下来,您将在视图上创建触发器来处理插入和更新。

CREATE TRIGGER InsertTrigger on OldB INSTEAD OF INSERT
AS
BEGIN
INSERT INTO B (id, data) SELECT id, data FROM inserted;
UPDATE AB SET primary_b = 0 WHERE b_id IN (SELECT id FROM inserted);
INSERT INTO AB (a_id, b_id, primary_b) SELECT a_id, id, 1 FROM inserted;
END 
GO

你会做一些类似的事情,而不是更新,除了你必须通过删除和添加行来管理A到B链接的变化。我还没有检查出错误的代码,但我将在接下来的一个小时左右,如果需要,发布更新。

您可能需要一些视图和触发器的组合

最新更新