简体   繁体   中英

SQL unique constraint on either of 2 columns

I have a table in SQL that I would like to have a unique constraint so that any of two values cannot already exist.

for example if I have 2 columns, I would like it to not insert if the value in column B does not exist in column A or column B.

Is this possible and if so how is it done?

example:

Column A | Column B
--------------------
     4   |   6

I would want any object that tries to insert 4 or 6 not to be allowed into the table

You can create a function which takes in these values & create a check constraint on it (referencing your functions return values) to your table.

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))

Trigger with ROLLBACK TRANSACTION is the way to go.

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

When one want to enforce a multi-row constraint that is not offered by the database engine, the obvious solution is use of a trigger or stored procedure. This often does not work because the database isolates the transactions the triggers and stored procedures run in, allowing violations in the presense of concurrency.

Instead turn the constraint into something that the database engine will enforce.

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

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM