Sql-Server

INSTEAD OF INSERT 不顯示更改

  • April 3, 2021

這是我的桌子:

CREATE TABLE [MyTable]
(
   [GroupId]     INT        NOT NULL,
   [ItemId]      INT        NOT NULL,
   [Data]        INT        NOT NULL,
   PRIMARY KEY CLUSTERED ([GroupId], [ItemId]),
   CONSTRAINT [FK_MyTable_tblGroup] FOREIGN KEY ([GroupId]) REFERENCES [tblGroup] ([Id])
);

我使用此觸發器ItemID在插入時生成:

CREATE TRIGGER [Trigger_MyTable_OnInsert]
ON [MyTable]
INSTEAD OF INSERT
AS
BEGIN
   INSERT INTO MyTable([GroupId], [ItemId], [Data])
   SELECT [GroupId],
       ISNULL((SELECT MAX(ItemId)
               FROM MyTable
               WHERE MyTable.GroupId = GroupId), 0) + 1,
       [Data]
   FROM  inserted i
END

在插入時,新ItemId值被插入到表中但不顯示:

插入行

使用實體框架時也存在此問題,我發現這部分數據庫存在問題。

我正在嘗試ItemId為每個GroupId. ItemId每個組都是唯一的,而不是表,這就是為什麼我不能使用IDENTITY.

最後我發現我必須使用OUTPUT命令。

在 INSTEAD OF 觸發器中使用 OUTPUT

這是固定 SQL 觸發器:

CREATE TRIGGER [Trigger_MyTable_OnInsert]
ON [MyTable]
INSTEAD OF INSERT
AS
BEGIN
   INSERT INTO MyTable([GroupId], [ItemId], [Data])
   OUTPUT INSERTED.[ItemId] as [ItemId]
   SELECT [GroupId],
       ISNULL((SELECT MAX(ItemId)
               FROM MyTable
               WHERE MyTable.GroupId = GroupId), 0) + 1,
       [Data]
   FROM  inserted i
END

正如我所說,使用EntityFrameworkCore時存在此問題。要解決這個問題,我們必須告訴 Entity Framework,這個值在呼叫Add()方法後會發生變化。

要解決這個問題,只需在DbContext類中添加以下方法即可:

entity.Property(table => table.ItemId).ValueGeneratedOnAdd();

為了清楚起見,程式碼的結果如下:

protected override void OnModelCreating(ModelBuilder modelBuilder)
{
   modelBuilder.Entity<MyTable>(entity =>
   {
       entity.HasKey(e => new { e.GroupId, e.ItemId });
       entity.Property(table => table.ItemId).ValueGeneratedOnAdd();
       entity.ToTable("MyTable");
   });
}

直接回答問題,問題是:

WHERE MyTable.GroupId = GroupId

您尚未GroupId在該表達式的右側指定您的意思。

SQL 標準規定 SQL Server 必須將其解析到最內層範圍,因此您有效地編寫了:

WHERE MyTable.GroupId = MyTable.GroupId

你應該寫:

WHERE MyTable.GroupId = i.GroupId

db<>小提琴展示

觸發器還有其他問題,例如不能正確處理多行插入,以及在並發下不安全。

我的一篇相關文章:序列表

引用自:https://dba.stackexchange.com/questions/249496