我认为这是一个好人。首先,我不知道触发器是什么,现在可能会变得很明显。
触发器是否适合维护数据库模式之间的向后兼容性?
假设我在版本1中有1对多的关系。在版本2中,这已经变为多对多。正确实现的触发器是否能够处理这个以便允许两个版本在同一个数据库上运行?这是个好主意吗?
答案 0 :(得分: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
上的活动可以保留T1ID
中的现有T2
列,以便向后兼容。
这肯定是可能的,但是你需要解决一大堆问题:
T1ID
中有多行,您对T2
写了哪个T1_T2
值?T1ID
中的T2
会发生什么 - 设置为NULL,选择另一个值?T2ID
删除与T1_T2
匹配的所有行,该怎么办?是否应删除T2
的行?让T1ID
设置为NULL?T1ID
中更新T2
且T1_T2
中不存在任何行,这是错误还是应插入新行?T1
中的行没有特定T2
T1ID
删除一行
我相信还有更多。您可以解决所有这些问题,但是您永远无法完全模拟旧版行为,以便100%使用版本1模式。
如果您能够解决上述所有问题,那么您可以使用触发器执行这些维护任务。正如我所说,它不会是100%,所以你可能仍然需要调整版本1的应用程序来解决他们的一些期望。
答案 1 :(得分: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关系。一种选择是将primary_b
类型bit
列添加到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
除了必须通过删除和添加AB中的行来管理A到B链接中的更改之外,您将执行类似的操作而不是更新。我还没有检查此代码是否有错误,但我会在接下来的一个小时左右发布并在必要时发布更新。
答案 2 :(得分:0)
您可能需要一些视图和触发器的组合。