0

GEOGRAPHY我有一个使用类型存储位置的地图表。由于 Entity Framework Core 不支持空间类型,我必须在我的应用程序中使用和列来映射MapView视图。然后,我在使用触发器插入或更新视图时将这些和值转换为 a 。LatLongLatLonggeography::PointINSTEAD OF

例子:

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);

我收到此错误:

子查询返回超过 1 个值。当子查询跟随 =、!=、<、<=、>、>= 或子查询用作表达式时,这是不允许的。

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

4

2 回答 2

3

这是因为这个声明:

(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
于 2018-09-10T19:42:03.123 回答
3

您可能不希望无效的 INSERT 静默失败。因此,只需跳过 null 检查,geography::Point如果有人尝试插入 NULL,该函数将引发错误。例如

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
于 2018-09-10T19:45:51.240 回答