Sql server 如何定义“非唯一”约束,在INSERT上断言现有值?

Sql server 如何定义“非唯一”约束,在INSERT上断言现有值?,sql-server,unique-constraint,distinct-values,Sql Server,Unique Constraint,Distinct Values,更新:我现在摒弃了这个问题背后的想法,而倾向于一种不同的设计。然而,就目前的问题而言,给出的答案是一个很好的答案。我很高兴地接受了 我想实现与SQL Server中的相反的功能 插入新行时,必须确保已存在的一个值被重新用于特定列,否则必须创建使用新值的行,请参见下面的注释: INSERT INTO [dbo].[Item] (/*...*/ [LogicalId]) VALUES (/*...*/ 123) GO 如果LogicalId的

更新:我现在摒弃了这个问题背后的想法,而倾向于一种不同的设计。然而,就目前的问题而言,给出的答案是一个很好的答案。我很高兴地接受了

我想实现与SQL Server中的相反的功能

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

INSERT INTO [dbo].[Item]
       (/*...*/
       [LogicalId])
VALUES
       (/*...*/
       123)
GO
如果LogicalId的值不在现有值中,则此操作必须失败

因为这个值来自一个序列,所以我尝试使用这个序列添加一个约束子句,如下所示:

但这导致了一个错误

在此上下文中不允许子查询。只允许使用标量表达式

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


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

当您以这样的方式描述它时,这似乎是一个奇怪的要求,但是,这是因为您从错误的角度看待它。您在这里所追求的当然是一个外键约束,只是看起来您缺少了包含外键的表

因此,您需要创建所述表,然后创建外键约束

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

这似乎是一个奇怪的要求,当你描述它的方式,但是,这是因为你从错误的角度看这件事。您在这里所追求的当然是一个外键约束,只是看起来您缺少了包含外键的表

因此,您需要创建所述表,然后创建外键约束

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

可以使用带有检查约束的自定义项。这可能是使用检查约束实现您所描述的操作的唯一方法。另一个选项是在插入之后使用触发器,或者使用触发器代替插入。考虑到无法插入任何新值,为什么不创建一个包含所有可能值的新表,然后创建一个外键约束?@Larnu可能有新值。我只想禁止用户使用任意值,我想让DB自动分配这些值,当用户提供空值时,请参见您在帖子@Marcel中所描述的内容。您明确表示要阻止用户在列中创建新的不同值。停止用户插入到列中,并插入新的不同值是完全不同的。“一个是基于权限的,一个是基于约束的。在这个阶段,你需要重新问你的问题,@Marcel。”。你在问题中问的和你看起来想要的是两件完全不同的事情。然而,改变你的问题会使我的答案完全无效,这是社会所不赞成的。你最好现在就提出一个新问题,并解释你真正想要的,而不是你认为你想要的。不要发布。可以使用带有检查约束的自定义项。这可能是使用检查约束实现您所描述的操作的唯一方法。另一个选项是在插入之后使用触发器,或者使用触发器代替插入。考虑到无法插入任何新值,为什么不创建一个包含所有可能值的新表,然后创建一个外键约束?@Larnu可能有新值。我只想禁止用户使用任意值,我想让DB自动分配这些值,当用户提供空值时,请参见您在帖子@Marcel中所描述的内容。您明确表示要阻止用户在列中创建新的不同值。停止用户插入到列中,并插入新的不同值是完全不同的。“一个是基于权限的,一个是基于约束的。在这个阶段,你需要重新问你的问题,@Marcel。”。你在问题中问的和你看起来想要的是两件完全不同的事情。然而,改变你的问题会使我的答案完全无效,这是社会所不赞成的。你最好现在就提出一个新问题,并解释你真正想要的,而不是你认为你想要的。不要发布一个。如果没有新的LogicalId,这将起作用,但会有。请参阅注释和注释。我希望逻辑Id是由数据库而不是用户分配的。如果没有新的LogicalId,这将起作用,但会有。请参阅注释和注释。我希望逻辑Id由数据库而不是用户分配。