Использование функции sql для ограничения CHECK для вновь вставленной строки
Прежде всего мне нужна помощь в этом для моей дипломной работы. Я делаю всю базу данных на SQL Server 2008, выпуск 2. Проблема в проверочном ограничении, использующем функцию, которая работает сама по себе, но не с использованием в ограничении. Результатом ограничения должно быть что-то вроде этого: работник может ездить только в одну деловую поездку в день.
Столовые Деловые поездки:
CREATE TABLE SluzebniCesta(
idSluzCesty int PRIMARY KEY NOT NULL,
DatumCesty DATE NOT NULL,
CasOdjezdu TIME(0) NOT NULL,
CasPrijezdu TIME(0),
CONSTRAINT Odjezd_prijezd CHECK(CasPrijezdu > DATEADD(hour,2,CasOdjezdu))
);
Таблица, которая содержит работников, которые отправляются в командировку:
CREATE TABLE ZamNaCeste(
idZamNaCeste int PRIMARY KEY NOT NULL,
SluzebCestaID int NOT NULL,
ZamestnanecID int NOT NULL,
FOREIGN KEY (ZamestnanecID) REFERENCES Zamestnanec(idZamestnance),
FOREIGN KEY (SluzebCestaID) REFERENCES SluzebniCesta(idSluzCesty)
);
Внешний ключ ZamestnanecID является идентификатором сотрудника, а SluzebCestaID - идентификатором командировки.
Теперь функция:
CREATE FUNCTION myCheckZamNaCeste(@SluzebCestaID int, @ZamestnanecID int)
RETURNS int
AS
BEGIN
DECLARE @retVal int;
DECLARE @Zamestnanec int;
DECLARE @SluzebniCesta int;
SET @Zamestnanec = (SELECT idZamestnance FROM Zamestnanec WHERE idZamestnance=@ZamestnanecID);
SET @SluzebniCesta = (SELECT idSluzCesty FROM SluzebniCesta WHERE idSluzCesty=@SluzebCestaID);
IF EXISTS ( SELECT DatumCesty FROM SluzebniCesta
WHERE idSluzCesty = @SluzebniCesta
AND DatumCesty IN (SELECT DatumCesty FROM ZamNaCeste
LEFT JOIN SluzebniCesta
ON ZamNaCeste.SluzebCestaID = SluzebniCesta.idSluzCesty
WHERE ZamestnanecID=@Zamestnanec))
BEGIN
SET @retVal=0;
END
ELSE
BEGIN
SET @retVal=1;
END
return @retVal
END
GO
И таблица изменения таблицы, которая содержит данные о сотрудниках и их поездках:
ALTER TABLE ZamNaCeste
ADD CONSTRAINT check_cesty_zamestnance CHECK(dbo.myCheckZamNaCeste(SluzebCestaID,ZamestnanecID)=1);
И когда я пытаюсь ввести любую новую строку, ограничение нарушается, даже если функция выдает правильные данные. возврат 1 - это хороший результат....
2 ответа
Во-первых, я не уверен, но похоже, что два set
операторы в функции собираются извлекать из таблиц те же самые значения, которые они уже имеют, передаваемые в качестве параметров.
Во-вторых, я не вижу ничего ограничивающего поездки в тот же день. В любом месте.
Если вы хотите ограничить поездку сотрудника одной поездкой в день, это легко.
CREATE TABLE ZamNaCeste(
idZamNaCeste int PRIMARY KEY NOT NULL,
SluzebCestaID int NOT NULL,
ZamestnanecID int NOT NULL,
TripDate date not null,
FOREIGN KEY (ZamestnanecID) REFERENCES Zamestnanec(idZamestnance),
FOREIGN KEY (SluzebCestaID) REFERENCES SluzebniCesta(idSluzCesty),
constraint UQ_OneTripPerDay unique( ZamestnanecID, TripDate )
);
Уникальное ограничение гарантирует, что один и тот же сотрудник не может зарегистрировать более одной поездки в один и тот же день.
Ну, в конце концов, я решил с более сложным и лучше выглядящим решением. Занятость ограничена временем прибытия и отъезда. И я решил это с помощью функции, которая возвращает количество неправильных вхождений, если его ноль, чем все в порядке, и это работает:
SELECT COUNT(*) FROM(SELECT * FROM SluzebniCesta JOIN ZamNaCeste
ON SluzebniCesta.idSluzCesty = ZamNaCeste.SluzebCestaID) AS a
JOIN (SELECT * FROM SluzebniCesta2 JOIN ZamNaCeste
ON SluzebniCesta.idSluzCesty = ZamNaCeste.SluzebCestaID)AS b
ON a.SluzebCestaID b.SluzebCestaID
AND a.CasOdjezdu b.CasOdjezdu
AND a.ZamestnanecID = b.ZamestnanecID
AND (SELECT SluzebniCesta.DatumCesty FROM SluzebniCesta
WHERE SluzebniCesta.idSluzCesty = a.SluzebCestaID) = (SELECT SluzebniCesta.DatumCesty
FROM SluzebniCesta WHERE SluzebniCesta.idSluzCesty = b.SluzebCestaID)