Ошибка вставки нескольких строк в представление с помощью триггера INSTEAD OF - PullRequest
0 голосов
/ 10 сентября 2018

У меня есть таблица карт, в которой хранится местоположение, используя тип 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 ]

0 голосов
/ 10 сентября 2018

Вы, вероятно, не хотите, чтобы неверный INSERT молча провалился.Поэтому просто пропустите проверку нуля, и функция geography::Point выдаст ошибку, если кто-то попытается вставить NULL.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
0 голосов
/ 10 сентября 2018

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

(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
...