Сравнение данных вставки с существующими данными в SQL

#sql #sql-server

#sql #sql-сервер

Вопрос:

Название может вводить в заблуждение, я просто не могу понять это.

У меня есть 3 таблицы; Employee, EmployeeSchedule и LocalStore. В таблице Employee есть столбец типа данных bit с именем «IsManager», в EmployeeSchedule дни просто помечены как «Понедельник» — «Воскресенье», и каждое хранилище имеет уникальный StoreID: введите описание изображения здесь

Правило, которое я хочу реализовать, заключается в следующем:

В магазине не может быть более 1 менеджера в день.

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

Я думаю о чем-то подобном, как я могу проверить, что менеджер еще не назначен этому хранилищу в тот же день?

 USE [StoreSystem]
GO
/****** Object:  Trigger [dbo].[CheckManagerAndDay]    Script Date: 2020-12-14 10:56:28 ******/
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
ALTER TRIGGER [dbo].[CheckManagerAndDay]
     ON [dbo].[EmployeeSchedule]
     AFTER INSERT, UPDATE
 AS
 BEGIN
     SET NOCOUNT ON;

     IF EXISTS (
         SELECT *
         FROM EmployeeSchedule
         JOIN Employee ON Employee.ID = EmployeeID
         JOIN LocalStore ON LocalStore.ID = StoreID
         WHERE IsManager = 1 and StoreID = ?? and Day = ??
     )
     BEGIN
         THROW 50000, 'Cannot have more than one manager on the same day.', 1;
     END
 END
 

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

1. В каком контексте вы думали о запуске кода, который вы нам показываете? Ad-hoc SQL? Хранимая процедура? Триггер? Может быть понятнее (при условии, что не ad-hoc), если вы можете показать нам больше этого контекста.

2. Запускайте, если не рекомендуется использовать другой способ.

Ответ №1:

Я нахожу это немного болезненным для реализации в SQL Server. Почему? Поскольку триггеры SQL Server устанавливаются на основе. Они предназначены для обработки нескольких строк. Это означает, что дубликаты могут появляться двумя разными способами:

  • В хранилище есть существующий менеджер, и новые данные вставляют второй.
  • Существующих менеджеров нет, но у новых данных есть два.

Ой.

Существует альтернативный способ — который не использует триггеры. Но есть сложность. isManager Флаг избыточно хранится в EmployeeSchedule . Затем мы используем внешний ключ, чтобы убедиться, что он правильный, и уникальный индекс для нужного вам свойства:

 alter table Employee add constraint unq_isManager_id
    unique (isManager, Id);

alter table EmployeeSchedule add constraint fk_employeeschedule_isManager_EmployeeId
    foreign key (isManager, EmployeeId) references Employee(isManager, EmployeeId);
 

А затем уникальное ограничение, которое делает то, что вы хотите:

 create unique index unq_employeeschedule_day_manager
    on employeeschedule(day)
    where isManager = 1;
 

Вуаля! Никаких триггеров!

Вы также должны исправить свою модель данных, чтобы day она хранилась в date виде, а не в виде строки. Хранение значений даты / времени в виде строк — действительно плохая привычка.

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

1. Хотя, если Day это день недели (так предполагает описание), целочисленное кодирование может быть более подходящим, чем произвольное date .