Альтернатива проверке ограничений в представлениях - PullRequest
4 голосов
/ 17 марта 2012

Итак, у меня есть две таблицы:

Requests
--------
Id
RequestSchemeId
ReceivedByUserId

ForwardedRequests
-----------------
Id
RequestId (FK to Id column of Requests Table)
ForwardedToUserId

и одно представление

ForwardedRequestsInRequestSchemes
---------------------------------
Requests.RequestSchemeId
Requests.ReceivedByUserId
ForwardedRequests.ForwardedToUserId

Каков стандартный / рекомендуемый способ добавления ограничения эквивалента в Requests.ReceivedByUserId != ForwardedRequests.ForwardedToUserId в представлении?

Я знаю, что проверочные ограничения не разрешены в представлениях.Использование SQL Server 2008.

РЕДАКТИРОВАНИЕ:

Это дополнительный вопрос к этому вопросу .

Бизнес-правила:

  1. Один и тот же запрос может быть переслан нескольким пользователям.Следовательно, столбец Id в таблице ForwardedRequests.

  2. Пользователь может получить только один Запрос для конкретной RequestScheme.Поэтому я создал ограничение UniqueKey для RequestSchemeId + ReceivedByUserId в таблице запросов.

  3. Запрос может быть перенаправлен другому пользователю, только если пересылаемый пользователь еще не имеет перенаправленного запроса по той же схемеот любого другого пользователя.Поэтому, как предложил Мартин в связанном вопросе , я создал представление из двух таблиц и добавил уникальное ограничение для Requests.RequestSchemeId + ForwardedRequests.ForwardedToUserId.

  4. Бизнес-правило, о котором идет речь, заключается в том, что получатель запроса не может переслать его самому себе.

Ответы [ 2 ]

9 голосов
/ 17 марта 2012

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

1) Вы можете добавить к индексированному представлению ForwardedRequestsInRequestSchemes дополнительный столбец 1/(ForwardedToUserId - ReceivedByUserId) AS FailIfSame, который увеличил бы Divide by zero error, если два значения одинаковы,Это означает, что вы в конечном итоге сохраните избыточный столбец в индексированном представлении.

2) Вы можете создать новое представление, которое возвращает любые такие строки, перекрестно соединенные в двухстрочную таблицу, а затем определить уникальное ограничение для этогоПосмотреть.Это представление всегда будет пустым.

CREATE TABLE dbo.TwoRows(C INT) INSERT INTO dbo.TwoRows VALUES(1),(1)

GO

CREATE VIEW dbo.FailIfForwardedUserEqualToReceivedByUser
WITH SCHEMABINDING 
AS
  SELECT 1 AS C
  FROM   dbo.ForwardedRequests FR 
         INNER JOIN dbo.Requests R 
           ON R.Id = FR.RequestId AND R.ReceivedByUserId = FR.ForwardedToUserId
         CROSS JOIN dbo.TwoRows

GO

CREATE UNIQUE CLUSTERED INDEX ix ON 
     dbo.FailIfForwardedUserEqualToReceivedByUser(C)
2 голосов
/ 17 марта 2012

Один из способов - запретить update, insert, delete права на таблицы и обеспечить соблюдение бизнес-требований с помощью хранимой процедуры. Например,

create procedure dbo.AddRequestForward(
    @requestId int
,   @forwardedToUserId int)
as
insert  ForwardedRequests
        (ForwardedRequests, ForwardedRequests)
select  @requestId
,       @forwardedToUserId
where   not exists
        (
        select  *
        from    Requests
        where   Id = @requestId
                and @forwardedToUserId = @forwardedToUserId
        )

if @@rowcount = 0
    return -1 -- Forwarded and Received identical user
return 1 -- Success
go
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...