Entry tags:
SQL - вопрос
Есть такая таблица, для связей объектов, и в ней два поля, куда вписываются id объектов. Нужны такие ограничения:
1. Нельзя привязать объект сам к себе: ALTER TABLE [dbo].[Relations] ADD CHECK (GUID1 <> GUID2)
2. Нельзя привязать один объект к другому больше, чем один раз: CREATE UNIQUE INDEX [GUIDsUnique] ON [dbo].[Relations]
Осталось только сочинить запрос, который проверит существующую уже таблицу на перевернутые пары. Делов-то. И обедать.
UPD: Сытое брюхо подсказало выход:
1. Нельзя привязать объект сам к себе: ALTER TABLE [dbo].[Relations] ADD CHECK (GUID1 <> GUID2)
2. Нельзя привязать один объект к другому больше, чем один раз: CREATE UNIQUE INDEX [GUIDsUnique] ON [dbo].[Relations]
([GUID1] ASC, [GUID2] ASC)
3. Нельзя привязать один объект к другому, если другой уже привязан к первому. Как это реализовать на уровне базы данных?
3. Нельзя привязать один объект к другому, если другой уже привязан к первому. Как это реализовать на уровне базы данных?
4. Не забыл ли я чего?
UPD: Видимо, я сделаю так:
-- проверка привязки объекта к себе самому
ALTER TABLE [dbo].[Relations] ADD CHECK (GUID1 <> GUID2)
-- проверка повторной привязки
CREATE UNIQUE INDEX [GUIDsUnique] ON [dbo].[Relations] ([GUID1] ASC, [GUID2] ASC)
-- триггер на добавление/изменение, который просто уберет из таблицы все (максимум одну) перевернутые пары. Они ведь по смыслу совершенно идентичны той, которая только что появилась
Я не ошибся нигде?
UPD: еще чуть более элегантное решение: не надо что-то делать, если не надо это делать:
-- проверка привязки объекта к себе самому
ALTER TABLE [dbo].[Relations] ADD CHECK (GUID1 <> GUID2)
-- проверка повторной привязки
CREATE UNIQUE INDEX [GUIDsUnique] ON [dbo].[Relations] ([GUID1] ASC, [GUID2] ASC)
-- триггер на добавление/изменение, который просто уберет из таблицы все (максимум одну) перевернутые пары. Они ведь по смыслу совершенно идентичны той, которая только что появилась
Я не ошибся нигде?
UPD: еще чуть более элегантное решение: не надо что-то делать, если не надо это делать:
ALTER TRIGGER [dbo].[CheckReversedPairs_Insert]
ON [dbo].[Call_Related]
INSTEAD OF INSERT
AS
BEGIN
if 0 = (select count(*)
from call_related, inserted
where call_related.callguid1=inserted.callguid2 and call_related.callguid2=inserted.callguid1)
insert into call_related
select * from inserted
END
Осталось только сочинить запрос, который проверит существующую уже таблицу на перевернутые пары. Делов-то. И обедать.
UPD: Сытое брюхо подсказало выход:
SELECT Call_Related.*
FROM Call_Related INNER JOIN
Call_Related AS Call_Related_1 ON Call_Related.CallGUID1 = Call_Related_1.CallGUID2 AND Call_Related.CallGUID2 = Call_Related_1.CallGUID1 AND
Call_Related.CallGUID1 < Call_Related.CallGUID2

no subject
no subject
no subject
no subject
no subject
создать вычисляемое поле, в котором будет хеш или любое другое однозначное соединение Guid1 и Guid2 и повесить на поле уникальный индекс. Чтобы для пары Guid1 и Guid2 хеш не зависел от порядка их следования, хеш можно строить, предварительно отсортировав guid-ы по значению. Щас еще подумаю..
no subject
no subject
Кроме того, я лично вообще триггеры почти не юзаю. Можешь сделать SP для вставки, а еще можешь рулить процессом в бизнес-слое - если за _эту_ целостность отвечает у тебя он, а не БД; при этом, в таблице оставляешь только жесткие констрейнты, без логики.
no subject
Можно сделать так, чтобы триггер, если не может сохранить, поднимал еггог. Не знаю, или это намного лучше.
no subject
И ваще, пойду-ка я побегаю.
no subject
no subject
no subject
no subject
no subject
no subject