微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

SQL Server:看起来有序的唯一复合键

如何解决SQL Server:看起来有序的唯一复合键

我创建了一个包含 2 个整数列 pkId1pkId2 的小型测试表。我将主键设置为包含两列的组合(首先是 pkId1,然后是 pkId2)。

现在我按以下顺序插入了一些值:(1,1)(1,2)(2,1)(2,2)。我原以为 (2,1) 会失败,但它没有。我怎样才能强迫它失败?

我可以将其签入我的应用程序,但我想在 sql 端执行此操作。 另外,我考虑过使用存储过程,但我想知道表的设计器中是否有为复合键设置的设置。

编辑

pkId1pkId2 的顺序很重要。例如,如果 (2,1) 已经在表中,则不应接受 (1,2)。这样做的原因是因为该行表示两个实体之间的链接。因此,应该读到有一个从 2 到 1 的链接(2,1)和一个从 1 到 2 的链接(1,2)。

至于 (1,1),(2,2) 等两列中的相同值,它们被接受,因为它们是特例。

解决方法

一个选项是创建一个 PERSISTED 列

示例

SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO

CREATE TABLE [dbo].[TestTable](
    [pkId1] [int] NOT NULL,[pkId2] [int] NOT NULL,[pkuc]  AS (case when [pkId1]<[pkId2] 
                     then concat([pkId1],'-',[pkId2]) 
                     else concat([pkId2],[pkId1]) 
                end) PERSISTED NOT NULL UNIQUE
) ON [PRIMARY]
GO

测试

Insert Into [dbo].[TestTable] (pkId1,pkId2) values (1,2)
Insert Into [dbo].[TestTable] (pkId1,pkId2) values (2,1)

Select * from [dbo].[TestTable]

更新表格

pkId1   pkId2   pkuc
1       2       1-2
,

出现了两个相对简单的选项。


1.检查约束和“代替”触发器

如果我们创建约束 for row in open(path): idx = 0 real_idx = idx + 1 with open(path,"r") as c: emotion,image,usage = c.readlines()[real_idx].split(",") if usage == "Training\n": train_labels.append(int(emotion)) imageArr = [] imageArr.append(image) train_images.append(imageArr) elif usage == "PublicTest\n" or usage == "PrivateTest\n": test_labels.append(int(emotion)) imageArr = [] imageArr.append(image) test_images.append(imageArr) else: print("This row was not assigned to any usage!") idx += 1 def load_data(): return train_images,train_labels,test_images,test_labels format_data(path) load_data()``` ,则可以满足要求,如 SMor's comment 中所述。然而,问题是这也会阻塞 (2,1) 的插入。

为了解决这个问题,我们在表上创建了一个 pkId1 <= pkId2 触发器来交换值:

INSTEAD OF

2.强制执行约束的索引视图

我们在表上创建了一个索引视图,并交换了值。视图本身的唯一约束强制执行该要求,因此 (2,1) 的单个插入不会被阻止,(2,1) 或 (1,2) 的进一步插入被阻止:

CREATE TRIGGER TrgINS ON dbo.Table
INSTEAD OF INSERT AS

SET NOCOUNT ON;

INSERT dbo.Table (pkId1,pkId2)
SELECT
  IIF(pkId1 > pkId2,pkId2,pkId1),IIF(pkId1 > pkId2,pkId1,pkId2)
FROM inserted;

GO

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。