Получение «Недопустимого имени столбца» в триггере

#sql #sql-server

#sql #sql-сервер

Вопрос:

Итак, я пытаюсь создать триггер, который обновит столбец, вызываемый TOTAL_CURSOS из моей таблицы TOTALES , с количеством доступных курсов. Триггер произойдет, когда я вставлю значение в свою таблицу CURSO . Проблема, с которой я сталкиваюсь, связана с моими int значениями DURACION и. COSTO

Вот мой код триггера:

 CREATE TRIGGER [TR_CURSO] ON [CURSO] FOR INSERT
AS
    
    UPDATE
        TOTALES
    SET
        TOTAL_CURSOS = ( SELECT COUNT(CODIGO) FROM CURSO );
    
    INSERT INTO BITACORA (
        MOMENTO,
        DESCRIPCION
    )
    VALUES (
        SYSDATETIME(),
        
        'SE INSERTO EL MAESTRO CON RFC DE: '  
        (SELECT RFC_I FROM INSERTED)  
        ' DEL CURSO: '  
        (SELECT NOMBRE FROM INSERTED)  
        ' CON COSTO DE: ' 
        CAST(COSTO AS nvarchar(10) )  
        ' CON FECHA DE: '   (GETDATE())  
        ' CON LA DURACION DE: '  
        CAST(DURACION AS nvarchar(5))  
        'Y EL CODIGO DE: '  
        (SELECT CODIGO FROM INSERTED)  
        ' POR EL USUARIO: '  
        CAST((CURRENT_USER) AS CHAR)
    );
 

Проблема, с которой я сталкиваюсь в настоящее время, заключается в том, что он не распознает DURACION и COSTO как допустимые столбцы.

Вот моя структура таблицы для CURSO.

 CREATE TABLE CURSO(
    CODIGO                 CHAR(5)   NOT NULL,
    NOMBRE                 CHAR(40)  NOT NULL,
    COSTO                  INT       NOT NULL,
    FECHA_INI              DATE      NOT NULL,
    DURACION               INT       NOT NULL,
    RFC_I                  CHAR(13)      NULL
);

CREATE TABLE TOTALES(
    TOTAL_INSTRUCTORES     INT           NULL,
    TOTAL_CURSOS           INT           NULL,
    TOTAL_ESTUDIANTES      INT           NULL
);

CREATE TABLE BITACORA(
    MOMENTO                CHAR(30)  NOT NULL,
    DESCRIPCION            CHAR(150) NOT NULL
);
 

Комментарии:

1. Ваши структуры таблиц? Пожалуйста, опубликуйте свои структуры таблиц, чтобы многие разработчики могли помочь вам с этой проблемой.

2. Откуда они должны взяться? Вы в основном выполняете вставку с этими столбцами, не указывая, откуда они. Вы хотите извлечь их из INSERTED, как и другие столбцы?

3. Да, я попытался выполнить следующее, ВСТАВИЛ.COSTO, но я получаю сообщение об ошибке, что оно не может быть привязано.

4. Вместо использования a TRIGGER , почему бы вместо этого не использовать индексированное представление? Триггеры не так надежны, как индексированные представления, которые имеют привязку к схеме.

5. В данном конкретном случае я должен использовать триггер.

Ответ №1:

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

Например, попробуйте это, измените эти :

       CAST(COSTO AS nvarchar(10) )  
        ' CON FECHA DE: '   (GETDATE())  
        ' CON LA DURACION DE: '  
        CAST(DURACION AS nvarchar(5))  
 

Для:

       CAST((SELECT COSTO FROM INSERTED.CURSO) AS nvarchar(10) )  
        ' CON FECHA DE: '   (GETDATE())  
        ' CON LA DURACION DE: '  
        CAST((SELECT DURACION FROM INSERTED.CURSO) AS nvarchar(5))  
 

Это может сработать или нет. Идея состоит в том, чтобы найти то, что работает, делая небольшие шаги.

Комментарии:

1. хай @ Дай, спасибо, идея здесь в том, что op должен вместо того, чтобы пробовать сложные операторы, тестировать и взламывать простые и собирать из них сложный

2. Я просто форматировал ваш код, я не придавал никакого значения.

3. @Dai, я знаю, почему thx, и мой комментарий просто для того, чтобы побудить op попробовать что-то, если намерение неясно из краткости ответа

Ответ №2:

Вы можете изменить вставку из значений на вставку из select.

 CREATE TRIGGER [TR_CURSO] ON [CURSO]
AFTER INSERT
AS
BEGIN
    UPDATE
        TOTALES
    SET
        TOTAL_CURSOS = ( SELECT COUNT(CODIGO) FROM CURSO );
    
    INSERT INTO BITACORA (
      MOMENTO,
      DESCRIPCION
    )
    SELECT 
      SYSDATETIME() AS MOMENTO,
      CONCAT (
        'SE INSERTO EL MAESTRO CON RFC DE: ', RTRIM(RFC_I), 
        ' DEL CURSO: ', RTRIM(NOMBRE), 
        ' CON COSTO DE: ', COSTO, 
        ' CON FECHA DE: ', GETDATE(), 
        ' CON LA DURACION DE: ', DURACION, 
        'Y EL CODIGO DE: ', RTRIM(CODIGO), 
        ' POR EL USUARIO: ', CURRENT_USER
      ) AS DESCRIPCION
    FROM INSERTED;
    
END;
 

Демонстрация в db<>fiddle здесь

Комментарии:

1. Триггер всегда должен проверять, действительно ли были вставлены строки, прежде чем что-либо делать. Вставка нулевых строк все равно приведет к выполнению триггера, который затем обновит первую таблицу (вызывая выполнение триггера обновления, если он определен), а затем вставит нулевые строки во вторую таблицу (вызывая выполнение триггера вставки, если он определен) и так далее.

2. @SMor Триггер after insert не запускается при сбое вставки. Смотрите демонстрацию.