SQL-триггер с параметром

#node.js #sql-server #triggers

#node.js #sql-сервер #триггеры

Вопрос:

У меня есть приложение nodejs с SQL Server. Я хочу иметь возможность обновлять таблицу для «конкретной организации» на основе действия вставки и удаления. Допустим, у меня есть 2 таблицы следующим образом:

  • Проект: projId, OrgID, projName
  • Задачи: идентификатор задачи, идентификатор проекта, имя задачи
  • Пользователи: идентификатор пользователя, идентификатор организации, имя пользователя
  • ОрганизациясТатьи: количество проектов, количество пользователей, количество задач OrgID

Итак, допустим, я добавляю новый проект для организации, где OrgID = 1. Моя инструкция insert из Nodejs будет:

 insert into project (projId, orgId, projName) 
values (${'projId'}, ${'orgId'}, 'New Project');
  

Я хочу написать триггер в SQL Server, который добавляет 1 к numberOfProjects столбцу с orgId переданным значением.

 create trigger updateProjectAfterInsert 
on project 
after insert 
as 
begin 
    update OrganizationStats 
    set numprojects = numberOfProjects   1 
    where orgId = 'THE_INSERTED_ORGID_VALUE';
end;
  

Моя проблема в том, что я не знаю, как передать ${'orgId'} триггеру.

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

1. Используйте вставленные / удаленные псевдотаблицы.

2. Вы также предполагаете, что количество вставленных строк всегда равно 1 — распространенная ошибка. Но зачем вообще это делать? Значение можно легко определить, подсчитав связанные строки, когда это необходимо, и оно ВСЕГДА будет правильным. Вы забыли об удалениях? Можно ли перемещать проект между организациями?

3. Лично я не рекомендую хранить значения, которые могут быть вычислены с помощью агрегата. Если вам нужна такая информация, легко доступная, вам лучше сделать a VIEW со значением там, на мой взгляд.

Ответ №1:

Я собираюсь расширить свой комментарий здесь:

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

Под этим я подразумеваю, что NumProjects в таблице «нет права» OrganizationStats , вместо этого оно должно вычисляться в то время, когда требуется информация. Вы не можете использовать агрегатную функцию в определении вычисляемого столбца без скалярной функции, и они могут быть довольно медленными. Вместо этого я рекомендую создать VIEW (или, если вы предпочитаете функцию табличного значения), чтобы предоставить вам информацию из таблицы:

 CREATE VIEW dbo.vw_OrganisationStats AS

    SELECT {Columns from OrganizationStats},
           P.Projects AS NumProjects
    FROM dbo.OrganizationStats OS
         CROSS APPLY (SELECT COUNT(*) AS Projects
                      FROM dbo.Projects P
                      WHERE P.OrgID = OS.OrgID) P;
  

Я использую a CROSS APPLY с подзапросом, так как тогда вам не нужен огромный GROUP BY в конце.

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

1. Итак, учитывая вышеизложенное, нужно ли мне создать еще 2 представления для вычисления количества numberOfUsers и numberOfTasks, или другие два столбца могут быть вычислены в том же представлении?

2. Вы бы добавили в то же представление.

3. итак, учитывая структуру таблицы в исходном вопросе, я не уверен, что все они попадут в один запрос представления.. @Lamu Не могли бы вы помочь с примером кода?

4. «Не могли бы вы помочь с примером кода?» В моем вопросе есть один, @SeanD . Я не знаю вашего дизайна или деталей требований, которые не рассматриваются в вопросе, но вы, безусловно, можете использовать несколько агрегатных функций в одном VIEW . Если вы не знаете, как реализовать вышеизложенное, вам лучше задать новый вопрос, так как в конечном итоге вы аннулируете оба ответа здесь, если измените этот вопрос.

Ответ №2:

Я думаю, что вы хотите, чтобы это было что-то вроде этого:

   CREATE TRIGGER updateProjectAfterInsert 
  ON Project 
  AFTER INSERT 
  AS 
  BEGIN 
      UPDATE OrganizationStats 
         SET NumProjects = NumProjects   1 
       WHERE OrgId IN (SELECT OrgId FROM inserted);
  END;
  

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

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

1. Обратите внимание, что если 2 проекта для одной и той же организации вставляются одновременно, это будет работать, но не так, как ожидает OP.

2. Hrm, да, если это возможный случай, то » 1″, скорее всего, должно быть вычислено с помощью коррелированного подзапроса.

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

4. AFTER INSERT триггеры не возникают после DELETE @SeanD .

5. Добавьте еще один триггер AFTER DELETE для обработки удалений, @SeanD