【问题标题】:SQL Server Trigger Tables with foreign keys带有外键的 SQL Server 触发器表
【发布时间】:2010-11-14 23:57:11
【问题描述】:

我有以下情况(SQL Server Express):

  • 通过 pk-fk 约束连接 2 个表
  • 连接这两个表的视图
  • 使用数据库的程序只能访问视图
  • 在视图中插入而不是触发器

这个想法是触发器将数据输入到 1. 表中 -> 通过 IDENTITY 创建一个新的 PK,第二个表现在必须包含 1. 表的 ID 作为其主键的一部分...

如何在多连接环境下访问1.表新创建的PK?这是数据库的简化/修改版本:

CREATE TABLE Training (  
Training_ID INT IDENTITY NOT NULL PRIMARY KEY,  
Name NVARCHAR(30) NOT NULL);

CREATE TABLE Kilometer (
Training_ID INT NOT NULL REFERENCES Training(Training_ID),  
Kilometer_ID INT NOT NULL,
Timestamp DATETIME NOT NULL,
PRIMARY KEY(Training_ID, Kilometer_ID);

CREATE VIEW TrainingView (  
SELECT t.Name, k.Timestamp
FROM Training t LEFT JOIN Kilometer k ON (t.Training_ID = k.Training_ID));

CREATE TRIGGER TrainingTrigger ON TrainingView INSTEAD OF INSERT AS BEGIN
INSERT INTO Training(Name) SELECT Name FROM inserted;
INSERT INTO Kilometer(Training_ID, Kilometer_ID, Timestamp) SELECT @@Identity, 0, Timestamp FROM inserted;
END;

由于数据库中的其他定义,Kilometer_ID 的默认“0”是强制性的,合并这两个表不是一个选项... 虽然触发器似乎正常工作,但我不确定它是否会在多用户环境中(@@Identity 会发生什么,如果另一个连接改变了表?)

这个触发器有更好的解决方案吗?

问候迈克尔

【问题讨论】:

    标签: sql-server triggers identity


    【解决方案1】:

    如果您对 @@Identity 的关注是唯一的问题,请使用 SCOPE_IDENTITY() ,它会返回来自同一范围的最近创建的 id。

    此处解释了差异:http://blog.sqlauthority.com/2007/03/25/sql-server-identity-vs-scope_identity-vs-ident_current-retrieve-last-inserted-identity-of-record/

    【讨论】:

    • 感谢您的链接,您对设计还有其他顾虑吗?
    • 我可能只是为这两个插入存储了一个过程,但是您的触发器看起来不错。我不确定我是否真的了解表格的内容,但结构看起来没问题,只要您不介意您不能在一个语句中插入多行,正如 Matt 解释的那样。
    • 好的,我可能过于简化了示例代码,目前并不真正需要在一个语句中插入多行(至少根据当前要求:))
    【解决方案2】:

    如果在单次插入的低容量环境中,您的方法可能会一直有效。在 SQL Server 中,如果使用 SCOPE_IDENTITY 会更好,因为它只从当前作用域获取身份。

    如果您想一次在此视图中插入多行(例如,insert into TrainingView select ...),这将会中断,因为您需要多个 TrainingID。为此,您可以使用 SQL Server's OUTPUT clause 来获取该插入的所有 ID。

    【讨论】:

    • 感谢您的回答,我会更好地更新到 SCOPE_IDENTITY。如果我理解正确,该函数将返回触发器创建的最后一个身份,无论触发器并行执行的频率或数据库中的其他位置更新身份。我说的对吗?
    • 我不确定你的意思。 SCOPE_IDENTITY() 将返回您在特定会话插入中的特定例程的最后一个身份,无论数据库中发生了什么或调用 SCOPE_IDENTITY 需要多长时间。所以,如果你插入但保持你的窗口/连接打开,其他人插入,那么你可以调用 SCOPE_IDENTITY(),你得到的是你最后插入的 ID,而不是他们的。
    猜你喜欢
    • 1970-01-01
    • 2016-06-04
    • 1970-01-01
    • 2021-09-04
    • 2015-12-07
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-09-18
    相关资源
    最近更新 更多