Как правильно переписать существующий триггер обновления для обработки нескольких обновленных значений? - PullRequest
0 голосов
/ 28 февраля 2020

У меня есть следующий код триггера, который хорошо работает при обновлении одной строки, но не работает при обновлении нескольких строк. Я хотел бы исправить это и искал решения.

Я рассматривал использование курсоров как простой способ решения проблемы, но я знаю, что они являются плохой идеей в триггерах.

Я хочу переписать это «правильным» способом , но я не эксперт в этой области и был бы признателен за некоторую помощь и совет, чтобы правильно переписать его.

Кто-нибудь может помочь?

Это код для текущего триггера:

BEGIN
    -- SET NOCOUNT ON added to prevent extra result sets from
    -- interfering with SELECT statements.
    SET NOCOUNT ON;

    DECLARE @Entity_Class_ID as int,
    @Entity_Identifier as varchar(50),
    @Postcode as varchar(100),
    @Latitude as numeric(18,9),
    @Longitude as numeric(18,9)

    IF EXISTS (SELECT * FROM DELETED) -- Check if an Update and use postcode from inserted 
    BEGIN
        IF (SELECT Postal_Code from INSERTED) != (SELECT Postal_Code from DELETED)
        BEGIN
            SET @Entity_Class_ID = (SELECT top 1 Entity_Class_ID from INSERTED order by Mailing_Address_ID desc)
            SET @Entity_Identifier = (SELECT top 1 Entity_Identifier from INSERTED order by Entity_Identifier desc)

            IF @Entity_Class_ID = 3 BEGIN
                SET @Postcode = (SELECT top 1 Postal_Code from INSERTED order by Mailing_Address_ID desc)

                    IF @Postcode is not null BEGIN

                    DECLARE @URL varchar(MAX)

                    SET @URL = 'http://dev.virtualearth.net/REST/v1/Locations/UK/' +
                    @Postcode +
                    '?o=xml&key=xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx'

                    DECLARE @Response varchar(8000)
                    DECLARE @XML xml
                    DECLARE @obj int
                    DECLARE @Result int
                    DECLARE @HTTPStatus int
                    DECLARE @ErrorMsg varchar(MAX)

                    EXEC @Result = sp_OACreate 'MSXML2.ServerXMLHttp', @Obj OUT

                    BEGIN TRY
                        EXEC @Result = sp_OAMethod @Obj, 'open', NULL, 'GET', @URL, false
                        EXEC @Result = sp_OAMethod @Obj, 'setRequestHeader', NULL, 'Content-Type', 'application/x-www-form-urlencoded'
                        EXEC @Result = sp_OAMethod @obj, send, NULL, ''
                        EXEC @Result = sp_OAGetProperty @Obj, 'status', @HTTPStatus OUT
                        EXEC @Result = sp_OAGetProperty @Obj, 'responseXML.xml', @Response OUT
                    END TRY
                    BEGIN CATCH
                        SET @ErrorMsg = ERROR_MESSAGE()
                    END CATCH

                    EXEC @Result = sp_OADestroy @Obj

                    IF (@ErrorMsg IS NOT NULL) OR (@HTTPStatus <> 200)
                    BEGIN
                        SET @ErrorMsg = 'Error in spGeocode: ' + ISNULL(@ErrorMsg, 'HTTP result is: ' + CAST(@HTTPStatus AS varchar(10)))
                        RAISERROR(@ErrorMsg, 16, 1, @HTTPStatus)
                        RETURN
                    END

                    SET @XML = CAST(@Response AS XML)

                    SET @Latitude = @XML.value('
                    declare namespace BM="http://schemas.microsoft.com/search/local/ws/rest/v1";
                    (/BM:Response/BM:ResourceSets/BM:ResourceSet/BM:Resources/BM:Location/BM:Point/BM:Latitude)[1]', 'numeric(18,9)')
                    SET @Longitude = @XML.value('
                    declare namespace BM="http://schemas.microsoft.com/search/local/ws/rest/v1";
                    (/BM:Response/BM:ResourceSets/BM:ResourceSet/BM:Resources/BM:Location/BM:Point/BM:Longitude)[1]', 'numeric(18,9)')
                    END


                    IF EXISTS (SELECT * FROM EXT_BI_Additional_Fields WHERE Project_ID = @Entity_Identifier)
                    UPDATE EXT_BI_Additional_Fields SET Latitude = @Latitude, Longitude = @Longitude 
                    WHERE Project_ID = @Entity_Identifier
                    ELSE
                    INSERT INTO EXT_BI_Additional_Fields (Project_ID, Latitude, Longitude, Project_Number, Project_Code)
                    select TOP (1) Project_ID, @Latitude, @Longitude, null as Project_Number, Project_Code
                    from  dbo.Project
                    WHERE Project_ID = @Entity_Identifier
                    order by Project_ID DESC


            END
        END
    END
END

Это таблица, в которой находится триггер (Mailing_Address):

enter image description here

Эта таблица обновляется с помощью результаты триггера (EXT_BI_Additional_Fields):

Project_ID  Latitude    Longitude   Project_Number  Project_Code
44          51.540180   -0.302364   12255           NULL
46          51.585091   -0.337701   12247           NULL

В настоящее время этот триггер работает так, что при обновлении Postal_Code в таблице «mailing_address» он отправляет обновленное значение Postal_Code в службу REST Bing Maps для геокодирования. Возвращенные значения широты и долготы затем либо вставляются, либо обновляются в таблицу «EXT_BI_Additional_Fields».

Для простоты обслуживания / читабельности человеком, указанная выше вставка также извлекает значения Project_Number и Project_Code из таблицы «Project»

...