[英]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)中管理此问题?
您的数据模型错误。
您需要一个仅包含id
和code
表(以及除date
之外的任何其他列都可能是相关的。让我们将此表codes
和id code_id
,因为这就是我的命名方式:
create table codes (
code_id int identity(1, 1) primary key,
code varchar(255) not null unique
);
那里。 现在, code_id
和code
之间的映射是一对一的。 接下来,仅使用code_id
和date
创建一个表:
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将调用一个以id
和code
为参数的函数。 该函数查询表,如果没有其他具有该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;
为什么不创建主键为id
, code
的Lookup表? 通过对code
施加UNIQUE
约束,您将确保code = 123
只会对id = 1
每对配对。 我们不能在不违反约束的情况下将code = 123
与id = 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.