Ошибка вставки нескольких строк в представление с помощью триггера INSTEAD OF

У меня есть таблица карт, которая хранит местоположение с помощью GEOGRAPHY тип. Поскольку Entity Framework Core не поддерживает пространственные типы, я должен отобразить MapView смотреть вместо Lat а также Long столбцы в моем приложении. Затем я преобразую эти Lat а также Long значения в geography::Point при вставке или обновлении в представлении с помощью INSTEAD 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 значения. Это недопустимо, если подзапрос следует =,! =, <, <=,>,> = Или когда подзапрос используется в качестве выражения.

Так что этот триггер работает только при одновременной вставке одной строки карты. Есть ли что-то, что я могу изменить внутри триггера, чтобы можно было вставлять несколько строк?

2 ответа

Решение

Это потому, что это утверждение:

(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 молча потерпел неудачу. Так что просто пропустите нулевую проверку и 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
Другие вопросы по тегам