如何定义 "NON-UNIQUE" 约束,在 INSERT 上断言现有值?

How to define a "NON-UNIQUE" constraint, asserting existing values on INSERT?

更新:我现在驳回了这个问题背后的想法,并赞成不同的设计。但是,就目前的问题而言,给出的答案是一个很好的答案。我很高兴地接受了它。


我想在 SQL 服务器中实现与 UNIQUE constraint 相反的东西。

在新行 INSERT 时,必须确保已存在的值之一被重复用于特定列(否则必须创建使用新值的行,请参见下面的注释):

INSERT INTO [dbo].[Item]
       (/*...*/
       [LogicalId])
VALUES
       (/*...*/
       123)
GO

如果 LogicalId 的值不在现有值中,这一定会失败。

因为这个值来自 SEQUENCE,我尝试使用 SEQUENCE 添加一个 CONSTRAINT 子句,如下所示:

ALTER TABLE Item  
ADD CONSTRAINT chkInsertNonUniqueLogicalId 
CHECK 
(
    ( LogicalId <= (SELECT current_value FROM sys.sequences WHERE name = 'SQ_LogicalId') ) AND
    ( LogicalId >= (SELECT minimum_value FROM sys.sequences WHERE name = 'SQ_LogicalId') ) 
);  
GO  

但这导致了一个错误

Subqueries are not allowed in this context. Only scalar expressions are allowed

如何在使用 INSERT 命令插入新行时断言同一列上的现有值?

注意:应具有新逻辑 ID(尚未使用的值)的行将使用 NULL 进行插入,从而导致具有上述序列的 DEFAULT 约束生效)。这样做的原因是具有数据库控制(而非用户控制)的逻辑 ID。

当您按照自己的方式描述它时,这似乎是一个奇怪的要求,但是,那是因为您从错误的角度看待它。您在这里肯定是外键约束,看来您缺少包含外键的 table。

因此,您需要创建所说的table,然后再创建外键约束。

CREATE TABLE dbo.Logical (LogicalID int NOT NULL
                          /*,...Other Columns? ...*/ );

ALTER TABLE dbo.Logical ADD CONSTRAINT PK_LogicalID
                        PRIMARY KEY CLUSTERED (LogicalID);
GO

INSERT INTO dbo.Logical (LogicalID /*,... Other Columns? ...*/)
SELECT DISTINCT LogicalID /*,... Other Columns? ...*/
FROM dbo.Items
WHERE LogicalID IS NOT NULL;
GO

ALTER TABLE dbo.Items ADD CONSTRAINT FK_LogicalID
                      FOREIGN KEY (LogicalID) REFERENCES dbo.Logical(LogicalID);