我在SQL中有一个表,希望设置唯一约束,以便任何两个值都不会重复存在。
例如,如果我有2列,我希望它在列B的值不存在于列A或列B时无法插入。
这是否可能,如果可能,如何实现?
示例:
Column A | Column B
--------------------
4 | 6
我希望任何试图插入4或6的对象都不被允许进入该表格
我在SQL中有一个表,希望设置唯一约束,以便任何两个值都不会重复存在。
例如,如果我有2列,我希望它在列B的值不存在于列A或列B时无法插入。
这是否可能,如果可能,如何实现?
示例:
Column A | Column B
--------------------
4 | 6
我希望任何试图插入4或6的对象都不被允许进入该表格
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))
使用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
当需要强制执行数据库引擎不提供的多行约束时,显而易见的解决方案是使用触发器或存储过程。然而,这种方法通常无法奏效,因为数据库会隔离触发器和存储过程运行的事务,从而允许在并发情况下违反约束。
相反,应将约束转化为数据库引擎可以强制执行的形式。
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