Оператор IF в хранимой процедуре (всего noob) - PullRequest
0 голосов
/ 25 мая 2019

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

Так что я понимаю, что мне нужно создать и запустить хранимую процедуру с агентом SQL Server, который бысделай это для меня.Хотя я никогда не писал хранимую процедуру, поэтому для меня это тоже практика.

SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
-- =============================================
-- Author:      Gary Senter
-- Create date: 5/25/2019
-- Description: Returns employee data.
-- =============================================
ALTER PROCEDURE [dbo].[spLocal_Safety_Sync] 
    @LastName NVARCHAR(50) = NULL, 
    @FirstName NVARCHAR(50) = NULL
AS
BEGIN
    SET NOCOUNT ON;

    DECLARE @injury_date DATETIME;
    DECLARE @short_name_1 VARCHAR(50);
    DECLARE @short_name_2 VARCHAR(50);
    DECLARE @short_name_3 VARCHAR(50);
    DECLARE @cc_roster_id_emp_1 INT;
    DECLARE @cc_roster_id_emp_2 INT;
    DECLARE @cc_roster_id_emp_3 INT;

    SELECT 
        @short_name_1 = effected_employee_1,
        @short_name_2 =  effected_employee_2, 
        @short_name_3 = effected_employee_3,
        @injury_date = IncidentDate 
    FROM
        HSEBE.dbo.MCA_Data
    WHERE  
        (Classification = 'XX RI' OR Classification = 'YY RI')
    ORDER BY 
        IncidentDate ASC

    IF LEN(@short_name_1) > 0 
    THEN
        SELECT @cc_roster_id_emp_1 = autoid 
        FROM cc_rosters 
        WHERE short_name = @short_name_1

    IF LEN(@short_name_2) > 0 
    THEN
        SELECT @cc_roster_id_emp_2 = autoid 
        FROM cc_rosters 
        WHERE short_name = @short_name_2

    IF LEN(@short_name_3) > 0 
    THEN
        SELECT @cc_roster_id_emp_3 = autoid 
        FROM cc_rosters 
        WHERE short_name = @short_name_3

    IF @cc_roster_id_emp_1 > 0 
    THEN
        UPDATE cc_rosters 
        SET most_recent_injury = @injury_date 
        WHERE autoid = @short_name_1

    IF @cc_roster_id_emp_2 > 0 
    THEN
        UPDATE cc_rosters 
        SET most_recent_injury = @injury_date 
        WHERE autoid = @short_name_2

    IF @cc_roster_id_emp_3 > 0 
    THEN
        UPDATE cc_rosters 
        SET most_recent_injury = @injury_date 
        WHERE autoid = @short_name_3
END

Я получаю следующие ошибки:

Сообщение 156, Уровень 15, Состояние 1, ПроцедураspLocal_Safety_Sync, строка 28
Неправильный синтаксис рядом с ключевым словом THEN.

Сообщение 156, уровень 15, состояние 1, процедура spLocal_Safety_Sync, строка 30
Неверный синтаксис рядом с ключевым словом "THEN".

Сообщение 156, уровень 15, состояние 1, процедура spLocal_Safety_Sync, строка 32
Неверный синтаксис рядом с ключевым словом 'THEN'.

Сообщение 156, уровень 15, состояние 1, процедура spLocal_Safety_Sync,Строка 35
Неверный синтаксис рядом с ключевым словом then.

Сообщение 156, Уровень 15, Состояние 1, Процедура spLocal_Safety_Sync, Строка 37
Неправильный синтаксис рядом с ключевым словом 'then'.

Сообщение 156, Уровень 15, Состояние 1, Процедура spLocal_Safety_Sync, Строка 39
Неверный синтаксис рядом с ключевым словом 'then'.

Не уверен, куда повернуть отсюда ....

Не всегда будет effect_employee_1,2,3, и иногда выбранное значение не будет возвращено из другой базы данных.

1 Ответ

0 голосов
/ 25 мая 2019

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

Прежде всего, позвольте мне объяснить, в чем я вижу проблему:

  1. Похоже, у вас плохая структура данных в таблице MCA_Data. Под этим я подразумеваю «плоскую» таблицу с несколькими сотрудниками в одной строке для инцидента. Обычно это PITA, когда речь идет о выполнении задач для просмотра данных во многих ситуациях. Обычно это таблица, в которой записи об инцидентах регистрируются отдельно для каждого человека, связанного с идентификатором инцидента и employeeID. Я понимаю, что вы, вероятно, не построили его, но стоит указать на вашу собственную информацию.

  2. По сути, эту проблему будет легче решить, если вы поймете, как эта нежелательная структура влияет на вашу задачу. По сути, это, на мой взгляд, основная проблема. PIVOT в SQL по сути переключает строки и столбцы. Если мы хотим найти максимальную дату инцидента для каждого сотрудника, нам просто нужно изменить данные в таблице MCA_Data для упрощения обработки, верно? Могут быть способы поворота данных с помощью кода - выберите ваш любимый - большинство людей на самом деле используют функцию PIVOT, где я склонен колебаться между CTE (обычными табличными выражениями) и PIVOT. ИМО CTE легче читать, когда вы их понимаете. Запустите этот код и посмотрите, вернет ли правильный результат.

       ; WITH CTE AS
       (
            SELECT Employee, AutoID, MAX(IncidentDate) AS MaxIncidentDate
            FROM
                (
                    SELECT 
                        effected_employee_1 AS Employee,
                        cc1.autoID AS AutoID,
                        MAX(IncidentDate) AS IncidentDate 
                    FROM 
                        HSEBE.dbo.MCA_Data mca
                    LEFT JOIN 
                        cc_rosters cc1 ON mac. effected_employee_1 = cc1. short_name
                    WHERE  
                        (Classification = 'XX RI' OR Classification = 'YY RI')
                        AND effected_employee_1 IS NOT NULL
                    GROUP BY 
                        effected_employee_1,
                        cc1.autoID
                    UNION
                    SELECT 
                        effected_employee_2 AS Employee,
                        cc2.AutoID  AS AutoID,
                        MAX(IncidentDate) AS IncidentDate 
                    FROM 
                        HSEBE.dbo.MCA_Data mca
                    LEFT JOIN 
                        cc_rosters cc2 ON mac. effected_employee_2 = cc2. short_name
                    WHERE  
                        (Classification = 'XX RI' OR Classification = 'YY RI')
                        AND effected_employee_2 IS NOT NULL 
                    GROUP BY 
                        effected_employee_2,
                        cc2.autoID                          
                    UNION
                    SELECT 
                        effected_employee_3 AS Employee, 
                        cc3.autoID AS AutoID,
                        MAX(IncidentDate) AS IncidentDate 
                    FROM 
                        HSEBE.dbo.MCA_Data mca
                    LEFT JOIN 
                        cc_rosters cc3 ON mac. effected_employee_3 = cc3. short_name
                    WHERE  
                        (Classification = 'XX RI' OR Classification = 'YY RI')
                        AND effected_employee_3 IS NOT NULL
                    GROUP BY 
                        effected_employee_3,
                        cc3.autoID      
                ) x
            GROUP BY 
                Employee, AutoID,
        )   
    SELECT * FROM CTE
    
    1. Теперь, когда у вас есть максимальные даты инцидентов для каждого сотрудника, столбцы которых не равны NULL, вы можете просто обновить отсюда. Обновление через объединения - это то, что вы хотите получить хорошо. Предотвращает все эти IF и переменные и различные утверждения. Это также помогает вам делать вещи на основе набора. Вы продолжите слышать это, продолжая свой путь обучения. Я предлагаю понять это!

      ; WITH CTE AS
      (
          SELECT Employee, AutoID, MAX(IncidentDate) AS MaxIncidentDate
          FROM
              (
                  SELECT 
                      effected_employee_1 AS Employee,
                      cc1.autoID AS AutoID,
                      MAX(IncidentDate) AS IncidentDate 
                  FROM 
                      HSEBE.dbo.MCA_Data mca
                  LEFT JOIN 
                      cc_rosters cc1 ON mac. effected_employee_1 = cc1. short_name
                  WHERE  
                      (Classification = 'XX RI' OR Classification = 'YY RI')
                      AND effected_employee_1 IS NOT NULL
                  GROUP BY 
                      effected_employee_1,
                      cc1.autoID
                  UNION
                  SELECT 
                      effected_employee_2 AS Employee,
                      cc2.AutoID  AS AutoID,
                      MAX(IncidentDate) AS IncidentDate 
                  FROM 
                      HSEBE.dbo.MCA_Data mca
                  LEFT JOIN 
                      cc_rosters cc2 ON mac. effected_employee_2 = cc2. short_name
                  WHERE  
                      (Classification = 'XX RI' OR Classification = 'YY RI')
                      AND effected_employee_2 IS NOT NULL 
                  GROUP BY 
                      effected_employee_2,
                      cc2.autoID                          
                  UNION
                  SELECT 
                      effected_employee_3 AS Employee, 
                      cc3.autoID AS AutoID,
                      MAX(IncidentDate) AS IncidentDate 
                  FROM 
                      HSEBE.dbo.MCA_Data mca
                  LEFT JOIN 
                      cc_rosters cc3 ON mac. effected_employee_3 = cc3. short_name
                  WHERE  
                      (Classification = 'XX RI' OR Classification = 'YY RI')
                      AND effected_employee_3 IS NOT NULL
                  GROUP BY 
                      effected_employee_3,
                      cc3.autoID      
              ) x
          GROUP BY 
              Employee, AutoID,
      )
      UPDATE r SET r.most_recent_injury = cte.MaxIncidentDate
      FROM cc_rosters r
      INNER JOIN CTE ON r.AutoID = CTE.AutoID AND r.short_name =cte.Employee;
      
    2. В процедурах, где у вас есть несколько команд, привыкните к использованию ';' символ для завершения каждой строки. Это хорошая практика.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...