使用 INSTEAD OF 触发器将多行插入到视图中时出错
Error inserting multiple rows into View with INSTEAD OF trigger
我有一个地图 table,它使用 GEOGRAPHY
类型存储位置。由于 Entity Framework Core 不支持空间类型,因此我必须在我的应用程序中映射 MapView
视图而不是 Lat
和 Long
列。然后,在使用 INSTEAD OF
触发器插入或更新视图时,我将这些 Lat
和 Long
值转换为 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
我有一个地图 table,它使用 GEOGRAPHY
类型存储位置。由于 Entity Framework Core 不支持空间类型,因此我必须在我的应用程序中映射 MapView
视图而不是 Lat
和 Long
列。然后,在使用 INSTEAD OF
触发器插入或更新视图时,我将这些 Lat
和 Long
值转换为 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