对于日志记录系统,我希望拥有以下数据库架构:
CREATE TABLE [dbo].[Categories] (
[Id] INT IDENTITY (1, 1) NOT NULL,
[App] NVARCHAR (30) NULL,
[Source] NVARCHAR (30) NULL,
[LogLevel] NVARCHAR (5) NULL,
[Logger] NVARCHAR (120) NULL,
CONSTRAINT [PK_Categories] PRIMARY KEY NONCLUSTERED ([Id] ASC),
CONSTRAINT [UK_Categories] UNIQUE NONCLUSTERED ([App] ASC, [Source] ASC, [LogLevel] ASC, [Logger] ASC)
);
CREATE TABLE [dbo].[Occurences] (
[PointInTime] BIGINT NOT NULL,
[CategoryId] INT NOT NULL,
[Noise] INT NOT NULL,
CONSTRAINT [PK_Occurences] PRIMARY KEY CLUSTERED ([PointInTime] ASC, [CategoryId] ASC, [Noise] ASC),
CONSTRAINT [FK_Category] FOREIGN KEY ([CategoryId]) REFERENCES [Categories] ([Id])
);
设计目标是允许大量日志记录数据,因为更昂贵的字符串被分解到单独的表中。
从语义上讲,这两个表形成了一个由该视图定义的逻辑表:
CREATE VIEW [dbo].[HistoricLogEntries]
AS SELECT o.PointInTime, o.Noise, c.App, c.[Source], c.LogLevel, c.Logger
FROM Occurences o
JOIN Categories c ON o.CategoryId = c.Id;
我现在想在视图上定义一个而不是插入触发器,这是我的麻烦开始的地方。我有以下尝试:
CREATE TRIGGER InsteadTrigger on [dbo].[HistoricLogEntries]
INSTEAD OF INSERT
AS
BEGIN
INSERT INTO Categories
SELECT i.App, i.[Source], i.LogLevel, i.Logger
FROM INSERTED i;
INSERT INTO Occurences
SELECT i.PointInTime, i.Noise, c.Id AS CategoryId
FROM INSERTED i
JOIN Categories c ON i.App = c.App AND i.[Source] = c.[Source] AND i.LogLevel = c.LogLevel AND i.Logger = c.Logger;
END
明显的第一个问题是第一个插入没有检查元组是否已经在数据库中。我知道在单值插入的情况下如何做到这一点,但在这里我必须考虑多行插入。
我无法解释的另一件事是,如果第一次插入成功,触发器甚至都不起作用。我得到一个外键违规 - 好像第一个插入实际上没有插入任何东西。
我认为这应该是一个常见的设置,所以也许有人有一些类似的示例代码?