(SQL) Попытка создания триггера, который отображает данные в историческую таблицу, как правило, с проверкой ошибок - PullRequest
0 голосов
/ 29 июня 2018

У меня есть две таблицы на текущий момент, расположенные в двух разных схемах dbo.table1 и historyyschema.table1history. Я создал триггер, который перемещает все исторические данные из таблицы1 (при вставке, удалении и обновлении) в таблицу1.

Первоначально я пытался спроектировать триггер для передачи информации с помощью INSERT INTO [историческая схема]. [Таблица1history] выберите @columns ...

Явное указание всех столбцов для передачи, но, поскольку две таблицы имеют одинаковые столбцы (за исключением того, что в истории есть дополнительные creation_timestamp и creation_status), я хотел добавить их в общем случае с помощью оператора select *. Я сделал это, потому что тогда, когда в базу данных добавлен столбец, я не хочу возвращаться и каждый раз вручную изменять триггер.

Мне нужен оператор try / catch в случае, если есть ошибка, но она не работает, потому что полученная ошибка не перехватывается try / catch (Полученная ошибка - неявное преобразование из-за неправильно выровненных таблиц). Мне было интересно, есть ли способ перебрать столбцы таблицы1 и убедиться, что столбцы отформатированы таким образом, что информация не будет создавать ошибку при вводе в таблицу1. История.

CREATE TRIGGER [dbo].[table1_History_Change] 
ON [dbo].[table1]
AFTER UPDATE, INSERT, DELETE
AS
    DECLARE @Now AS DateTIME = GETDATE()

    SELECT *
    INTO #ModifiedTemp
    FROM 
        (SELECT 'I' *, creation_status, @Now creation_timestamp
         FROM inserted
         UNION
         SELECT *, 'D' creation_status, @Now creation_timestamp
         FROM deleted) SubQuery

    IF (SELECT COUNT(*) FROM #ModifiedTemp WHERE creation_status = 'D') > 0 
       AND (SELECT COUNT(*) FROM #ModifiedTemp WHERE creation_status = 'I') > 0
    BEGIN
        DELETE FROM #ModifiedTemp 
        WHERE creation_status = 'D'

        UPDATE #ModifiedTemp 
        SET creation_status = 'U'
    END

    BEGIN TRY
        INSERT INTO [HistorySchema].[Table1History]
            SELECT * 
            FROM #ModifiedTemp
    END TRY
    BEGIN CATCH
        PRINT 'History unsuccessfully saved (ERROR: bundle_procedure_change)'
        DROP TABLE #ModifiedTemp
        RETURN
    END CATCH

    DROP TABLE #ModifiedTemp

(Это мои первые посты, так что если у вас есть какие-либо критические замечания, которые помогут мне улучшить их, они приветствуются:).)

ПРИМЕЧАНИЕ. Если таблицы отформатированы неправильно, я хочу, чтобы триггер просто не создавал историю, а выполнял транзакцию на главной таблице.

1 Ответ

0 голосов
/ 30 июня 2018

Весь ваш триггер может быть упрощен до чего-то близкого к этому. Я не знаю, какие колонки у вас действительно есть. Вы никогда не должны использовать * здесь, потому что если ваша базовая таблица изменится, ваш триггер сломается. Будьте явными со столбцами.

CREATE TRIGGER [dbo].[table1_History_Change] ON [dbo].[table1]
    after update, insert, delete as

    set nocount on;

    INSERT INTO [HistorySchema].[Table1History]
    (
        CreationStatus
        , creation_timestamp
        , Col1
    )
    select CreationStatus = case when i.ID is null then 'D' when d.ID is null then 'I' else 'U' end
        , creation_timestamp = getdate()
        , isnull(i.Col1, d.Col2) --this will get the new values for inserted and updated or the current value for a delete
    from inserted i 
    full outer join deleted d on d.ID = i.ID
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...