如果您在Map 表上的主键是单列Id,那么您在Images 表中的外键实际上就是MapId 列,它引用了Id 列在父表上。
如果Map 表上的主键是Id 的单列,那么您将无法插入与Id 具有相同值的另一行。
可以为IDENTITY列插入具有指定值的行,但是你必须做一个SET IDENTITY_INSERT tablename ON语句,然后你必须记住做一个对应的SET IDENTITY_INSERT tablename OFF语句。
为了实现 Map 表内容的历史记录,我会考虑创建一个单独的“MapHistory”表来存储更改历史记录,并使用触发器来维护它。
CREATE TABLE MapHistory (
[change_date] datetime NOT NULL,
[Id] int NOT NULL,
[CreatedAt] datetime NOT NULL,
...
要存储更新前Map 中行的“历史记录”,您可以在触发器中引用特殊的逻辑deleted 表。 (为了完整起见,当从 Map 表中删除一行时,我可能还会在历史表中存储一行。)
CREATE TRIGGER map_update ON Map AFTER UPDATE,DELETE AS
BEGIN
SET NOCOUNT ON
-- store column values as they existed prior to the update or delete
INSERT MapHistory (change_date, Id, CreatedAt, ... )
SELECT CURRDATE(), Id, CreatedAt, ... FROM deleted
END
使用这种方法,您的代码可以简单得多。您只需对Map 表执行UPDATE,数据库将负责维护MapHistory 表。
这种方法的一个小缺点是现在“当前”值在一个表中,而以前值的历史记录在另一个表中。
如果您希望将当前值也存储在MapHistory 表中,您可以修改触发器以触发AFTER INSERT, UPDATE,并改为引用特殊的逻辑inserted 表,以便创建一个“将插入的更新行复制到历史表中。
也可以在历史记录表中同时存储“旧”和“新”行,但这样您实际上会存储冗余数据。在这种情况下,您可能需要包含一个列,以指示该行是来自“已删除”表还是“插入”表。
CREATE TRIGGER map_update ON Map AFTER INSERT,UPDATE,DELETE AS
BEGIN
SET NOCOUNT ON
-- store column values as they existed prior to an update or delete
INSERT MapHistory (source, change_date, Id, CreatedAt, ... )
SELECT 'D', CURRDATE(), Id, CreatedAt, ... FROM deleted
-- store column values as they exist after an update or insert
INSERT MapHistory (source, change_date, Id, CreatedAt, ... )
SELECT 'I' CURRDATE(), Id, CreatedAt, ... FROM inserted
END
附录:
此方法允许您将Id IDENTITY 作为Map 表中的简单主键。我认为我在MapHistory 表中添加的change_date 列可能是多余的,它可能符合您在CreatedAt 列中的目的。