在两列组合MSSQL上创建约束

在两列组合MSSQL上创建约束,sql,sql-server,stored-procedures,sql-server-2005,Sql,Sql Server,Stored Procedures,Sql Server 2005,我有一个表,有两个列名Parent和Child,数据如下所示 | Parent | Child | |---------------------|------------------| | 100 | 101 | |---------------------|------------------| 我还在这两列上添加了唯一的约束,命令如下: ALTER TABLE Example ADD

我有一个表,有两个列名ParentChild,数据如下所示

|     Parent          |     Child        |
|---------------------|------------------|
|      100            |      101         |
|---------------------|------------------|
我还在这两列上添加了唯一的约束,命令如下:

ALTER TABLE Example ADD CONSTRAINT UC_Example UNIQUE (parent,child);
现在,如果我尝试在父对象中插入100,在子对象中插入101,则失败,这是正确的,但我也想停止反向插入 示例:101在父级和100在子级也应失败


有没有一种方法可以使用sql或过程或任何预定义的sql命令来执行此操作

CREATE TABLE Tab1 (
    Parent INT
    ,Child INT
    )

INSERT INTO Tab1
  VALUES (100,101),(100,102)
GO

---------------------------------------------------------------------------------------------------------------------------

CREATE FUNCTION dbo.fnc_RestrictedInsert (@NewParent INT, @NewChild INT)
RETURNS BIT
AS
BEGIN
    DECLARE @Count INT = 0;
    DECLARE @RetVal BIT = 1;

    SELECT @Count = COUNT(*)
      FROM Tab1
      WHERE (Parent = @NewParent AND Child = @NewChild)
        OR (Child = @NewParent AND Parent = @NewChild)

    SET @RetVal = CASE 
            WHEN @Count > 1
                THEN 0
            ELSE 1
            END

    RETURN @RetVal;
END

---------------------------------------------------------------------------------------------------------------------------

ALTER TABLE Tab1 WITH NOCHECK ADD CONSTRAINT [CK_Ins] CHECK (([dbo].[fnc_RestrictedInsert]([Parent], [Child]) = (1)))

---------------------------------------------------------------------------------------------------------------------------

INSERT INTO Tab1 VALUES (100,101)
INSERT INTO Tab1 VALUES (101,100)

INSERT INTO Tab1 VALUES (100,103)
alter table example add constraint unq_parent_child
    unique (min_id, max_id);

我会使用计算列来实现这一点。这样,就不需要定义额外的函数或触发器

alter table example add min_id as (case when parentId < childId then parentId else childId end) persisted;

alter table example add max_id as (case when parentId < childId then childId else parentId end) persisted;

我可能弄错了,但我非常确定,如果没有进一步的编码,这是不可能的。这不是约束应该如何工作的!无论如何,解决方法是创建一个执行此检查的函数,并在检查约束中使用此函数。。。但这可能会显著降低性能(取决于插入的记录数)。我建议您在插入触发器后创建,我想它应该始终是父子单向的。我在第一条评论(在OP下)中提示了性能,但没有收到任何有关数据量等的反馈。因此,有提示(在我的评论中)此功能可能是一种解决方法,但“这可能会显著降低性能(取决于插入的记录数)”什么的性能?这样的索引只会影响性能(负面)插入值时。表上至少有一个索引,因此这只是开销的另一个增量。但是……这应该比使用用户定义的函数或触发器要好,后者通常是性能杀手。