#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
.