我试图根据另一个表的值约束一个表的值。对于T1,列'col'允许为'A'或'B'。对于T2列,'col'允许为'C'或'D'。但如果T1.col为'B',T2.col不允许为'D'。它们具有T1.PK = T2.FK的多对一关系。如果我尝试在加入T1.col ='B'时在T2.col中插入D,它应该失败。
我看到了this,但我并没有尝试做任何聚合功能。我目前的尝试看起来像这样
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'
这可以解决您遇到的错误
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);
检查在插入值之前运行,因此,如果您的函数检查提交的值,当您设置错误值时它不会返回错误,但是当您尝试将其更改为有效值时它将...您在插入之前发送要验证的值...
使用@ 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);