繁体   English   中英

两个唯一列的非唯一组合

[英]non unique combination of two unique columns

我有列代码,id日期和其他一些日期的表。 这些列一起是主键。

primary key(id, code, date)

我希望它们在一起是独一无二的。 但是代码不能在具有两个不同ID的表中重复。 例如,这是一种可能的情况:

id   code  date        data
1    123   3/28/2018   "data 1"
1    123   4/28/2018   "data 2"

甚至这个

1    123   3/28/2018   "data 1"
1    124   3/28/2018   "data 2"

虽然不是:

id   code  date        data
1    123   3/28/2018   "data 1"
2    123   4/28/2018   "data 2"

仅当两行的ID均为1时,才可能有两行代码为“ 123”。“ 123”不能与任何其他ID组合。

如何在sql server(版本14)中管理此问题?

您的数据模型错误。

您需要一个仅包含idcode表(以及除date之外的任何其他列都可能是相关的。让我们将此表codes和id code_id ,因为这就是我的命名方式:

create table codes (
    code_id int identity(1, 1) primary key,
    code varchar(255) not null unique
);

那里。 现在, code_idcode之间的映射是一对一的。 接下来,仅使用code_iddate创建一个表:

create table code_dates (
    code_date_id int identity(1, 1) primary key,
    code_id int,
    date date,
    contraint fk_code_dates_code_id foreign key (code_id) references codes(code_id)
);

您可以使用code_id查找code 瞧! 您的数据模型是固定的。

Gordon的答案是最好的建议,但是将您的问题视为学术问题,除了您已有的PRIMARY KEY外,您还可以使用CHECK CONSTRAINT来管理所需的内容。

CHECK CONSTRAINT将调用一个以idcode为参数的函数。 该函数查询表,如果没有其他具有该code id ,则返回true否则返回false CONSTRAINT仅允许函数返回true行。

这可能会做到

create table tmp (id int not null,  code int not null, dt datetime not null,  data varchar(10)
                   primary key (id, code, dt));
create function dbo.CheckFunction(@id int, @code int)
returns int
as begin
    return (select count(*) from tmp t where t.id <> @id and t.code = @code) 
end;
alter table tmp
add constraint chk_CheckFunction
check (dbo.CheckFunction(id, code) = 0);

truncate table tmp;
insert into tmp values 
       (1 ,123, '3/28/2018', 'data 1')
     , (1 ,123, '4/28/2018', 'data 2')
     , (1 ,123, '5/28/2018', 'data 2');
select * from tmp;
select count(*) from tmp t where t.id <> 1 and t.code = 123;
insert into tmp values 
       (2 ,123, '3/28/2018', 'data 1');
select * from tmp;

drop table tmp;
drop function dbo.CheckFunction;

为什么不创建主键为idcode的Lookup表? 通过对code施加UNIQUE约束,您将确保code = 123只会对id = 1每对配对。 我们不能在不违反约束的情况下将code = 123id = 2放在一起。

然后在查阅表和您的业务表之间放置一个引用约束。 然后,引用约束将把约束从Lookup表转移到Business表,该表将坚持认为code = 123只能匹配id = 1每个匹配项。

就像是:

DROP TABLE Business;
DROP TABLE Lookup;

CREATE TABLE Lookup
(
    id INT NOT NULL,
    code INT NOT NULL UNIQUE,
    CONSTRAINT PK_Lookup Primary Key (id, code)
);

INSERT INTO Lookup VALUES (1, 123);
INSERT INTO Lookup VALUES (1, 124);
INSERT INTO Lookup VALUES (2, 123); -- Rejected

CREATE TABLE Business
(
  id int NOT NULL,
  code int NOT NULL,
  date date NOT NULL,
  data NVARCHAR(20) NOT NULL,
  CONSTRAINT PK_Business PRIMARY KEY (id, code, date),
  CONSTRAINT FK_Lookup FOREIGN KEY (id, code) REFERENCES Lookup (id, code)
);

INSERT INTO Business VALUES (1, 123, '2018-03-28', 'data 1');
INSERT INTO Business VALUES (1, 123, '2018-04-28', 'data 2');
INSERT INTO Business VALUES (1, 124, '2018-03-28', 'data 2');
INSERT INTO Business VALUES (2, 123, '2018-04-28', 'data 2'); -- Rejected

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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