使用 INSTEAD OF 触发器将多行插入到视图中时出错

Error inserting multiple rows into View with INSTEAD OF trigger

我有一个地图 table,它使用 GEOGRAPHY 类型存储位置。由于 Entity Framework Core 不支持空间类型,因此我必须在我的应用程序中映射 MapView 视图而不是 LatLong 列。然后,在使用 INSTEAD OF 触发器插入或更新视图时,我将这些 LatLong 值转换为 geography::Point

示例:

CREATE TRIGGER [dbo].[MapViewInsertInstead] ON [dbo].[MapView]
INSTEAD OF INSERT
AS
IF ((SELECT Lat FROM inserted) IS NOT NULL AND (SELECT Long FROM inserted) IS NOT NULL)
BEGIN
INSERT INTO [dbo].[Map] (HouseId, HousePoint)
    SELECT HouseId
    geography::Point(Lat, Long, 4326)
FROM inserted
END

这一段时间以来运行良好,但我一直都是一次插入一行。我现在正在执行包含地图数据的数据批量导入任务。当一次向视图中插入多行时,像这样:

INSERT INTO MapView (HouseId, Lat, Long)
VALUES(0x1, 10, 10), (0x2, 10, 10);

我收到这个错误:

Subquery returned more than 1 value. This is not permitted when the subquery follows =, !=, <, <= , >, >= or when the subquery is used as an expression.

因此,此触发器仅在一次插入单个地图行时才有效。我可以在触发器内部进行修改以允许插入多行吗?

这是因为这条语句:

(SELECT Lat FROM inserted) IS NOT NULL

需要一个值来与条件进行比较。

您可以通过删除 IF 语句来重写逻辑,并将检查合并到 INSERT 语句本身:

CREATE TRIGGER [dbo].[MapViewInsertInstead] ON [dbo].[MapView]
INSTEAD OF INSERT
AS
BEGIN
INSERT INTO [dbo].[Map] (HouseId, HousePoint)
    SELECT HouseId
    geography::Point(Lat, Long, 4326)
FROM inserted
WHERE Lat IS NOT NULL
  AND Long IS NOT NULL
END

您可能不希望无效的 INSERT 悄无声息地失败。所以只要跳过 null 检查,如果有人试图插入 NULL,geography::Point 函数就会引发错误。 EG

CREATE OR ALTER TRIGGER [dbo].[MapViewInsertInstead] ON [dbo].[MapView]
INSTEAD OF INSERT
AS
BEGIN
    set nocount on;

    INSERT INTO [dbo].[Map] (HouseId, HousePoint)
        SELECT HouseId, geography::Point(Lat, Long, 4326)
    FROM inserted;
END