簡體   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