我在SQL中有一个表,我希望有一个唯一约束,以便两个值中的任何一个都不能存在。
例如,如果我有2列,如果B列中的值不存在于A列或B列中,我希望不插入。
这可能吗?如果可以的话怎么做?
示例:
Column A | Column B
--------------------
4 | 6
我希望任何试图插入4或6的对象不允许进入表
答案 0 :(得分:0)
您可以创建一个接受这些值的功能。在它上面创建一个检查约束(引用你的函数返回值)。
create table t11 (Code int, code2 int)
create function fnCheckValues (@Val1 int, @Val2 int)
Returns int /*YOu can write a better implementation*/
as
Begin
DECLARE @CntRow int
IF(@Val1 IS NULL OR @Val2 IS NULL) RETURN 0
select @CntRow = count(*) from t11
where Code in (@Val1,@Val2 ) or Code2 in (@Val1,@Val2 )
RETURN @CntRow
End
GO
alter table t11 Add constraint CK_123 check ([dbo].[fnCheckValues]([Code],[code2])<=(1))
答案 1 :(得分:0)
使用ROLLBACK TRANSACTION进行触发即可。
create trigger dbo.something after insert as
begin
if exists ( select * from inserted where ...check here if your data already exists... )
begin
rollback transaction
raiserror ('some message', 16, 1)
end
end
答案 2 :(得分:0)
当想要强制执行数据库引擎不提供的多行约束时,显而易见的解决方案是使用触发器或存储过程。这通常不起作用,因为数据库隔离了触发器和存储过程运行的事务,允许违反并发性。
而是将约束转换为数据库引擎将强制执行的操作。
CREATE TABLE dbo.T (A INT, B INT)
GO
CREATE TABLE dbo.T_Constraint_Helper (ColumnName sysname PRIMARY KEY)
INSERT INTO dbo.T_Constraint_Helper (ColumnName)
VALUES ('A'), ('B')
GO
CREATE VIEW T_Constraint_VW
WITH SCHEMABINDING AS
SELECT CASE CH.ColumnName WHEN 'A' THEN T.A ELSE T.B END AS Value
FROM dbo.T
CROSS JOIN dbo.T_Constraint_Helper CH
GO
CREATE UNIQUE CLUSTERED INDEX FunnyConstraint_VW_UK ON dbo.T_Constraint_VW (Value)
GO
INSERT INTO T VALUES (1, 2)
-- works
INSERT INTO T VALUES (2, 3)
-- Msg 2601, Level 14, State 1, Line 1
-- Cannot insert duplicate key row in object 'dbo.T_Constraint_VW' with unique index 'T_Constraint_VW_UK'. The duplicate key value is (2).
INSERT INTO T VALUES (4, 4)
-- Msg 2601, Level 14, State 1, Line 1
-- Cannot insert duplicate key row in object 'dbo.T_Constraint_VW' with unique index 'T_Constraint_VW_UK'. The duplicate key value is (4).
INSERT INTO T VALUES (5, 6)
-- works