【问题标题】:Triggers for schema compatibility架构兼容性的触发器
【发布时间】:2011-09-30 10:49:39
【问题描述】:

我认为这是一个很好的。首先,我真的不知道触发器是什么,现在可能会变得很明显。

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

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

【问题讨论】:

  • 你可能应该,你知道的,先了解一下触发器 :)
  • 我知道。我会的,但我觉得我问了一个好问题。看看我得到的所有很棒的答案!每个人都可以阅读!
  • @Martin 认为即使是一个答案也与有人试图提供帮助无关,您可以投反对票,但不要再讽刺和忘恩负义

标签: sql database tsql triggers


【解决方案1】:

实现向后兼容性绝非易事。想象一下你有(版本 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,选择另一个值?
  • 如果从T1_T2 中删除匹配T2ID所有 行会怎样。是否应该删除来自T2 的行? T1ID 设置为 NULL 了吗?
  • 如果版本 1 应用程序更新 T2 中的 T1ID 并且 T1_T2 中不存在任何行,这是错误还是应该插入新行?
  • 如果T2 中没有行具有特定的T1ID,版本1 应用程序是否会假设它可以从T1 中删除一行

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


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

【讨论】:

  • 感谢您回答一般性问题。这将是我任意的、高度依赖应用程序和假设的实现。最后;选择最后一个;将 T1ID 设置为 NULL;错误;没有。
【解决方案2】:

是的,您可以通过使用 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

您将执行类似的操作而不是更新,但您必须通过删除和添加 AB 中的行来管理 A 到 B 链接中的更改。我尚未检查此代码是否有错误,但我会在接下来的一个小时左右,并在需要时发布更新。

【讨论】:

  • 我想对这两个答案都打勾,但由于 Ryan 是后起之秀......据我所知,仍然没有简单的方法可以做到这一点。需要多几行代码才能满足 Damien 的要求,而且可能还有更多的空白需要填补。
【解决方案3】:

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

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多