0

Я создаю самостоятельно связанные таблицы:Как избежать круговых отношений в SQL-Server?

Таблица Item столбцы:
ItemId INT - ПК;
Сумма денег - не менее; Цена денег - вычисленный столбец с использованием UDF, который извлекает значение в соответствии с количеством предков.
ParentItemId int - nullable, ссылка на другой ItemId в этой таблице.

Мне нужно избегать цикла, то есть, брат не может стать предком своих предков, то есть, если ItemId = 2 ParentItemId = 1, то ItemId 1 ParentItemId = 2 не должно быть разрешено.

Я не знаю, какая должна быть лучшая практика в этой ситуации. Я думаю, что я должен добавить CK, который получает значение Scalar из UDF или что-то еще.

EDIT: Другой вариант состоит в создании ВМЕСТО триггером и положить в 1 транзакции обновление поля ParentItemId и выбрав поле Цена от @@ RowIdentity, если он не отменить сделку, но я бы предпочел проверка UDF.

Любые идеи искренне приветствуются.

ответ

0

протестирована и работает просто отлично:

CREATE TRIGGER Item_UPDATE 
    ON Item 
    FOR INSERT, UPDATE 
AS 
BEGIN 

BEGIN TRY 
    SELECT Price FROM INSERTED 
END TRY 
BEGIN CATCH 
    RAISERROR('This item cannot be specified with this parent.', 16, 1) 
    ROLLBACK TRANSACTION; 
END CATCH 

END 
GO 
0

Насколько велика проблема в реальной жизни? Это может быть дорого, чтобы обнаружить эти ситуации (возможно, с помощью триггера). Фактически, это, вероятно, будет стоить вам больших усилий, по каждой транзакции, когда только крошечная подгруппа всех ваших транзакций когда-либо вызовет эту проблему.

Подумайте об этом в первую очередь.

+0

я, вероятно, необходимо убедиться, что в потоке предок не должен стать ребенком. Я сомневаюсь, какова должна быть лучшая практика. – Shimmy

+1

Лучшей практикой было бы не тратить слишком много времени на решение проблем, которые не произойдут. –

0

Простой трюк заключается в том, чтобы заставить ParentItemId быть меньше, чем ItemId. Это предотвращает замыкание цикла в этом простом контексте.

Однако есть нижняя сторона - если вам нужно по какой-либо причине удалить/вставить родителя, вам может потребоваться удалить/вставить все его дочерние элементы по порядку.

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

1

Нужно ли это обязательно применять на уровне базы данных?

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

+0

Да. Мне нужно, чтобы это было проверено на сервере. – Shimmy

+0

Да. Я должен быть проверен на сервере, так как к db будут доступны несколько приложений. – Shimmy

1

Проверяет, что это непросто реализовать, и возможные решения могут вызвать множество ошибок и проблем, которые могут быть сложнее первоначального. Обычно достаточно добавить управление для ввода пользователя и предотвратить бесконечный цикл чтения данных. Если ваше приложение использует хранимые процедуры без ORM, я бы выбрал реализацию этой логики в SP. В противном случае - справиться с этим в других слоях, а не в БД