2010-11-14 63 views
2

我有以下的情况(SQL Server Express的):通过PK-FK约束 SQL Server触发器表与外键

  • 是连接这两个表的视图连接

    • 2表
    • 的程序使用的数据库仅有权访问对视图的视图的
    • 一个代替触发器插入件

    的想法是,三gger将数据输入到表格中 - >通过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,如果另一个连接改变了表格)?

    是否有更好的解决方案来触发此触发器?

    格尔茨迈克尔

  • 回答

    2

    如果用@@认同你的关心是唯一的问题,使用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/

    +0

    感谢您的链接,您对设计有任何其他担忧吗? – MFH 2010-11-14 17:52:28

    +0

    我可能只是为两个插入存储了一个过程,但是您的触发器看起来很健康。我不确定我是否真的得到了表格的内容,但只要不介意你不能在一个语句中插入多行,就像Matt解释的那样,结构看起来很好。 – 2010-11-14 18:08:24

    +0

    好吧,我可能已经过分简化了示例代码,在一个语句中插入多行并不是真的需要当前(至少根据当前要求:)) – MFH 2010-11-14 19:55:50

    0

    你的方法可能是去上班几乎所有的时间,如果它在单个刀片的低容积环境。在SQL Server中,如果使用SCOPE_IDENTITY更好,因为它只从当前范围获取身份。

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

    +0

    感谢您的回答,我会更好地更新到SCOPE_IDENTITY。如果我理解正确,那么函数将返回触发器创建的最后一个标识,而不管触发器并行执行的频率如何或数据库中的其他位置更新了标识。我对吗? – MFH 2010-11-14 17:59:38

    +0

    我不确定你的意思。 SCOPE_IDENTITY()将返回特定会话中插入的特定例程的最后一个标识,而不管数据库中发生了什么或者需要多长时间调用SCOPE_IDENTITY。所以,如果你插入但是让你的窗口/连接保持打开状态,其他人插入,那么你会调用SCOPE_IDENTITY(),你会得到你最后插入的ID而不是他们的。 – Matt 2010-11-24 22:33:13