SQL Server: ограничение столбца на основе столбца в другой таблице - PullRequest
0 голосов
/ 20 марта 2019

Я пытаюсь ограничить значения одной таблицы на основе значений из другой. Для T1 столбец «col» может быть «A» или «B». Для столбца T2 столбец «col» может быть «C» или «D». Но T2.col не может быть «D», если T1.col «B». Они имеют отношение один к одному T1.PK = T2.FK. Если я попытаюсь вставить D в T2.col, когда он присоединится к T1.col = 'B', произойдет сбой.

Я видел это , но я не пытаюсь выполнять какие-либо агрегатные функции. Моя текущая попытка выглядит следующим образом

CREATE FUNCTION dbo.CheckAddition()
RETURNS bit
AS BEGIN RETURN (
    SELECT CASE 
        WHEN T2.col = 'C' THEN 1
        WHEN T2.col = 'D' AND T1.col = 'A' THEN 1
        ELSE 0 
    END AS 'Check'
    FROM T1 
    INNER JOIN T2
    ON T1.PK = T2.FK
) END

GO;
ALTER TABLE Shift ADD CONSTRAINT checkAdd CHECK (dbo.CheckAddition() = 1);

но так как это не агрегат, я получаю этот сбой.

Subquery returned more than 1 value. This is not permitted when the subquery follows =, !=, <, <= , >, >= or when the subquery is used as an expression.

Редактировать
Мои полные таблицы выглядят так

CREATE TABLE [dbo].[T1](
    [PK] [bigint] IDENTITY(1,1) NOT NULL,
    [col] [char](1) NOT NULL,
 CONSTRAINT [PK_T1] PRIMARY KEY CLUSTERED 
(
    [PK] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
) ON [PRIMARY]
GO

ALTER TABLE [dbo].[T1]  WITH CHECK ADD  CONSTRAINT [CK_T1] CHECK  (([col]='B' OR [col]='A'))
GO

ALTER TABLE [dbo].[T1] CHECK CONSTRAINT [CK_T1]
GO


CREATE TABLE [dbo].[T2](
    [PK] [bigint] IDENTITY(1,1) NOT NULL,
    [FK] [bigint] NOT NULL,
    [col] [char](1) NOT NULL,
 CONSTRAINT [PK_T2] PRIMARY KEY CLUSTERED 
(
    [PK] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
) ON [PRIMARY]
GO

ALTER TABLE [dbo].[T2]  WITH CHECK ADD  CONSTRAINT [FK_T2_T1] FOREIGN KEY([FK])
REFERENCES [dbo].[T1] ([PK])
GO

ALTER TABLE [dbo].[T2] CHECK CONSTRAINT [FK_T2_T1]
GO

ALTER TABLE [dbo].[T2]  WITH CHECK ADD  CONSTRAINT [CK_T2] CHECK  (([col]='D' OR [col]='C'))
GO

ALTER TABLE [dbo].[T2] CHECK CONSTRAINT [CK_T2]
GO

Я пытаюсь сделать так, чтобы T2.col не мог быть 'D', если соответствующий PK / FK в T1.col = 'A'

Ответы [ 2 ]

1 голос
/ 20 марта 2019

Это исправляет ошибку, которую вы получаете

CREATE FUNCTION dbo.CheckAddition()
RETURNS bit
AS BEGIN 
DECLARE @Res BIT

    SELECT @Res = CASE 
        WHEN T2.col = 'C' THEN 1
        WHEN T2.col = 'D' AND T1.col = 'A' THEN 1
        ELSE 0 
    END 
    FROM T1 
    INNER JOIN T2
    ON T1.PK = T2.FK
    RETURN @Res 
END

GO;
ALTER TABLE Shift ADD CONSTRAINT checkAdd CHECK (dbo.CheckAddition() = 1);

Но с точки зрения производительности лучше обеспечить это ...

CREATE FUNCTION dbo.CheckAddition(@FKValue INT, @Value CHAR(1))
    RETURNS bit
    AS BEGIN 
    DECLARE @Res BIT

        SELECT @Res = CASE 
            WHEN @Value = 'D' AND T1.Col = 'B' THEN 0
            ELSE 1 
        END 
        FROM T1
        WHERE T1.FK = @FKValue
        RETURN @Res 
    END

    GO;

ALTER TABLE T2 ADD CONSTRAINT checkValue CHECK (Col IN ('C','D'));
ALTER TABLE T2 ADD CONSTRAINT checkAdd CHECK (dbo.CheckAddition(FK, Col) = 1);

Проверка выполняется перед вставкой значения,поэтому, если ваша функция проверяет зафиксированные значения, она не выдаст ошибку, когда вы устанавливаете неправильное значение, но будет, когда вы попытаетесь изменить ее на действительную ... Таким образом, вы отправляете значения для проверкидо вставки ...

0 голосов
/ 20 марта 2019

Используя предложение @ HasanMahmood, это работает.

CREATE FUNCTION dbo.CheckAddition()
RETURNS bit
AS BEGIN RETURN (
    SELECT TOP 1 CASE 
        WHEN T2.col = 'C' THEN 1
        WHEN T2.col = 'D' AND T1.col = 'A' THEN 1
        ELSE 0 
    END AS 'Check'
    FROM T1 
    INNER JOIN T2
    ON T1.PK = T2.FK
    ORDER BY T2.PK DESC
) END

GO;
ALTER TABLE Shift ADD CONSTRAINT checkAdd CHECK (dbo.CheckAddition() = 1); 
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...