Sql server 插入的表在使用带有INSTEAD OF INSERT触发器的视图时出错
我正在尝试运行以下merge语句以插入行:Sql server 插入的表在使用带有INSTEAD OF INSERT触发器的视图时出错,sql-server,tsql,sql-server-2016,Sql Server,Tsql,Sql Server 2016,我正在尝试运行以下merge语句以插入行: MERGE sales.Widget USING ( VALUES ('19668651', 4.75)) AS widg (WidgetId, WidgetCost) ON 1=0 WHEN NOT MATCHED THEN INSERT (WidgetId, WidgetCost) VALUES (widg.WidgetId, widg.WidgetCost) OUTPUT INSERTED.Widget
MERGE sales.Widget
USING (
VALUES ('19668651', 4.75))
AS widg (WidgetId, WidgetCost)
ON 1=0
WHEN NOT MATCHED THEN
INSERT (WidgetId, WidgetCost)
VALUES (widg.WidgetId, widg.WidgetCost)
OUTPUT INSERTED.WidgetId
INTO @inserted;
GO
我被我得到的错误弄糊涂了:
不允许列引用“inserted.WidgetId”,因为它引用的基表在此语句中未被修改
我认为inserted
表只是传递给merge语句的值的内存表
那么,只要传入值,它为什么会关心我是否在修改“基”表呢
我可以清楚地看出,这与这样一个事实有关:我的视图上有一个触发器,而不是INSERT
触发器(因为它在正常表中工作正常)
但是为什么SQL Server不只是返回传入的值呢?(在本例中为WidgetId。)
以下是重现错误的脚本:
CREATE SCHEMA sales
GO
-- Create the base table
CREATE TABLE sales.Widget_OLD(
WIDGET_ID int NOT NULL,
WIDGET_COST money NOT NULL
CONSTRAINT PK_Widget PRIMARY KEY CLUSTERED (WIDGET_ID ASC)
)
GO
-- Create the overlay view
CREATE VIEW sales.Widget AS
SELECT widg.WIDGET_ID AS WidgetId, widg.WIDGET_COST AS WidgetCost
FROM sales.Widget_OLD widg
GO
-- create the instead of insert trigger
CREATE TRIGGER sales.InsertWidget ON sales.Widget
INSTEAD OF INSERT AS
BEGIN
INSERT INTO sales.Widget_OLD (WIDGET_ID, WIDGET_COST)
SELECT Inserted.WidgetId, inserted.WidgetCost
FROM Inserted
END
GO
DECLARE @inserted TABLE (WidgetId varchar(11) NOT null);
MERGE sales.Widget
USING (
VALUES ('19668651', 4.75))
AS widg (WidgetId, WidgetCost)
ON 1=0
WHEN NOT MATCHED THEN
INSERT (WidgetId, WidgetCost)
VALUES (widg.WidgetId, widg.WidgetCost)
OUTPUT INSERTED.WidgetId
INTO @inserted;
GO
-- Clean up
DROP TRIGGER sales.InsertWidget
DROP VIEW sales.Widget
DROP TABLE sales.Widget_OLD
DROP SCHEMA sales
go
注意:这是我的Entity Framework Core应用程序,当我尝试进行3+插入()时,问题是关于如何阻止EF Core使用
MERGE
。这是为了了解发生了什么。“但是为什么SQL Server不只是返回传入的值?”因为插入的不是指传入的值,而是指实际插入的值。换句话说,它必须推迟生成这些值,直到触发器实际确定它们是什么。这与仅仅输出输入大不相同,即使在这种情况下,触发器碰巧没有更改值,而且显然非常复杂,不支持这种特定场景。此外,为什么要使用merge
来实现简单的insert
?@ZoharPeled-简短回答:这是生成的代码。冗长的回答:当需要插入的行数超过3行时,一个名为Entity Framework Core(由Microsoft提供)的产品会为插入生成这样的代码。对于这个问题,我已经简化为一行,但是原始查询通过合并插入了3行。较长的答案:请参阅问题底部的链接,了解完整的细节和解决方法(作为答案)。