在 SQL 服务器中,有没有办法建立两个 table 之间的关系,其中一个 table 有 3 个唯一键,而 table 两个有 2 个唯一键?
Is there a way to relationship between two table which table one has 3 unique keys and table two has 2 unique keys in SQL Server?
我想在两个 table 之间创建关系,这是我的 table 结构
表 1:
ID INT PrimaryKey AUTO_INCREMENT,
CountryCode INT UNIQUE,
Division VARCHAR(4) UNIQUE,
SubDivision VARCHAR(10) UNIQUE
表 2:
ID INT PrimaryKey AUTO_INCREMENT,
CountryCode INT UNIQUE,
Division VARCHAR(4) UNIQUE,
ReportNo VARCHAR(10) UNIQUE
表 1:
ID |CountryCode |Division |SubDivision
-------+------------------+--------------+-----------
1 |IDN |A |A-1
2 |IDN |B |B-1
3 |IDN |B |B-2
表2
ID |CountryCode |Division |ReportNo
-------+------------------+--------------+-----------
1 |IDN |A |Re001
2 |IDN |A |Re002
3 |IDN |B |Re003
我想在 table2 (CountryCode, Division)
引用 table1 (CountryCode, Division)
的两个 table 之间建立关系。
所以当我想在table1 中删除CountryCode = IDN 和Division = A 时,SQL 会在table2 包含CountryCode = IDN 和Division = A 时提示错误.
我曾尝试在这两个 table 之间建立关系,但 SQL 服务器总是抛出此错误:
The column in table 'table1' do not match an existing primary key or unique constraint
任何人都可以指导我如何在这两个 table 之间建立关系吗?
提前致谢
你不能这样做。 SQL 服务器需要外键目标上的唯一约束(或主键约束)- 并且您在源中有重复项 table。
为此,您需要有一个单独的 table 来引用所有可能的 (CountryCode, Division)
组合。实际上,您的整个架构应该规范化为:
-- "top" table that stores the countries
create table countries (
country_id int primary key
name varchar(100)
);
-- the table that stores the divisions
create table divisions (
division_id int primary key,
country_id int references countries(country_id),
name varchar(100)
);
-- the table that stores the subdivisions
-- this corresponds to "table1" in your question
create table subdivisions (
subdivision_id int primary key,
division_id int references divisions(division_id),
name varchar(100)
);
-- the table that stores the reports
-- this corresponds to "table2" in your question
create table reports (
report_id int primary key,
division_id references divisions(division_id),
name varchar(100)
);
您可以使用 identity
列(这是 MySQL 的 AUTO_INCREMENT
的 SQL 服务器等效项)使主键自动生成。
例如,您将如何生成要为细分显示的当前输出:
select
sd.id,
c.name country,
d.name division,
sd.name subdivision
from subdivisions sd
inner join divisions d on d.division_id = sd.division_id
inner join countries c on c.country_id = d.country_id
正如 GMB 所回答的那样,由于重复,您不能以这种方式进行。 GMB 的回答是解决您问题的最佳方法。如果由于某种原因您不能听从他的建议,那么我的回答也许会有所帮助。
您可以在 CountryCode、Division、SubDivision 列上使用复合主键。然后将细分添加到Table2。然后在外键约束中引用这个主键。 (请注意,我的示例故意抛出错误以表明无法删除该值)
DROP TABLE IF EXISTS Table2;
DROP TABLE IF EXISTS Table1;
CREATE TABLE Table1
(ID INT IDENTITY(1,1)
, CountryCode CHAR(3)
, Division VARCHAR(4)
, SubDivision VARCHAR(10)
, CONSTRAINT PK_Table1 PRIMARY KEY(CountryCode, Division, SubDivision)
)
INSERT INTO Table1(CountryCode, Division, SubDivision)
VALUES ('IDN', 'A', 'A-1')
, ('IDN', 'B', 'B-1')
, ('IDN', 'B', 'B-2');
CREATE TABLE Table2
(ID INT IDENTITY(1,1) PRIMARY KEY
, CountryCode CHAR(3)
, Division VARCHAR(4)
, SubDivision VARCHAR(10)
, ReportNo VARCHAR(10)
, CONSTRAINT FK_CountryDivision FOREIGN KEY(CountryCode, Division, SubDivision) REFERENCES Table1(CountryCode, Division, SubDivision)
);
INSERT INTO Table2(CountryCode, Division, SubDivision, ReportNo)
VALUES ('IDN', 'A', 'A-1', 'Re001')
, ('IDN', 'B', 'B-1', 'Re002')
, ('IDN', 'B', 'B-2', 'Re003');
DELETE FROM Table1
WHERE Division = 'A';
当然,此更改可能会增加一整套新问题,例如,当报告针对整个部门时,细分值应该是多少。
ps。我不得不稍微更改示例表,因为值不匹配,即将字符串值转换为 int 列。
谢谢大家的回答。
但是在我的设计中我不能这样做,因为我一开始就错了。
@10676716 @GMB 先生给出了最棒的回答。
-- "top" table that stores the countries
create table countries (
country_id int primary key
name varchar(100)
);
-- the table that stores the divisions
create table divisions (
division_id int primary key,
country_id int references countries(country_id),
name varchar(100)
);
-- the table that stores the subdivisions
-- this corresponds to "table1" in your question
create table subdivisions (
subdivision_id int primary key,
division_id int references divisions(division_id),
name varchar(100)
);
-- the table that stores the reports
-- this corresponds to "table2" in your question
create table reports (
report_id int primary key,
division_id references divisions(division_id),
name varchar(100)
);
再次感谢专线小巴先生
我想在两个 table 之间创建关系,这是我的 table 结构
表 1:
ID INT PrimaryKey AUTO_INCREMENT,
CountryCode INT UNIQUE,
Division VARCHAR(4) UNIQUE,
SubDivision VARCHAR(10) UNIQUE
表 2:
ID INT PrimaryKey AUTO_INCREMENT,
CountryCode INT UNIQUE,
Division VARCHAR(4) UNIQUE,
ReportNo VARCHAR(10) UNIQUE
表 1:
ID |CountryCode |Division |SubDivision
-------+------------------+--------------+-----------
1 |IDN |A |A-1
2 |IDN |B |B-1
3 |IDN |B |B-2
表2
ID |CountryCode |Division |ReportNo
-------+------------------+--------------+-----------
1 |IDN |A |Re001
2 |IDN |A |Re002
3 |IDN |B |Re003
我想在 table2 (CountryCode, Division)
引用 table1 (CountryCode, Division)
的两个 table 之间建立关系。
所以当我想在table1 中删除CountryCode = IDN 和Division = A 时,SQL 会在table2 包含CountryCode = IDN 和Division = A 时提示错误.
我曾尝试在这两个 table 之间建立关系,但 SQL 服务器总是抛出此错误:
The column in table 'table1' do not match an existing primary key or unique constraint
任何人都可以指导我如何在这两个 table 之间建立关系吗?
提前致谢
你不能这样做。 SQL 服务器需要外键目标上的唯一约束(或主键约束)- 并且您在源中有重复项 table。
为此,您需要有一个单独的 table 来引用所有可能的 (CountryCode, Division)
组合。实际上,您的整个架构应该规范化为:
-- "top" table that stores the countries
create table countries (
country_id int primary key
name varchar(100)
);
-- the table that stores the divisions
create table divisions (
division_id int primary key,
country_id int references countries(country_id),
name varchar(100)
);
-- the table that stores the subdivisions
-- this corresponds to "table1" in your question
create table subdivisions (
subdivision_id int primary key,
division_id int references divisions(division_id),
name varchar(100)
);
-- the table that stores the reports
-- this corresponds to "table2" in your question
create table reports (
report_id int primary key,
division_id references divisions(division_id),
name varchar(100)
);
您可以使用 identity
列(这是 MySQL 的 AUTO_INCREMENT
的 SQL 服务器等效项)使主键自动生成。
例如,您将如何生成要为细分显示的当前输出:
select
sd.id,
c.name country,
d.name division,
sd.name subdivision
from subdivisions sd
inner join divisions d on d.division_id = sd.division_id
inner join countries c on c.country_id = d.country_id
正如 GMB 所回答的那样,由于重复,您不能以这种方式进行。 GMB 的回答是解决您问题的最佳方法。如果由于某种原因您不能听从他的建议,那么我的回答也许会有所帮助。
您可以在 CountryCode、Division、SubDivision 列上使用复合主键。然后将细分添加到Table2。然后在外键约束中引用这个主键。 (请注意,我的示例故意抛出错误以表明无法删除该值)
DROP TABLE IF EXISTS Table2;
DROP TABLE IF EXISTS Table1;
CREATE TABLE Table1
(ID INT IDENTITY(1,1)
, CountryCode CHAR(3)
, Division VARCHAR(4)
, SubDivision VARCHAR(10)
, CONSTRAINT PK_Table1 PRIMARY KEY(CountryCode, Division, SubDivision)
)
INSERT INTO Table1(CountryCode, Division, SubDivision)
VALUES ('IDN', 'A', 'A-1')
, ('IDN', 'B', 'B-1')
, ('IDN', 'B', 'B-2');
CREATE TABLE Table2
(ID INT IDENTITY(1,1) PRIMARY KEY
, CountryCode CHAR(3)
, Division VARCHAR(4)
, SubDivision VARCHAR(10)
, ReportNo VARCHAR(10)
, CONSTRAINT FK_CountryDivision FOREIGN KEY(CountryCode, Division, SubDivision) REFERENCES Table1(CountryCode, Division, SubDivision)
);
INSERT INTO Table2(CountryCode, Division, SubDivision, ReportNo)
VALUES ('IDN', 'A', 'A-1', 'Re001')
, ('IDN', 'B', 'B-1', 'Re002')
, ('IDN', 'B', 'B-2', 'Re003');
DELETE FROM Table1
WHERE Division = 'A';
当然,此更改可能会增加一整套新问题,例如,当报告针对整个部门时,细分值应该是多少。
ps。我不得不稍微更改示例表,因为值不匹配,即将字符串值转换为 int 列。
谢谢大家的回答。
但是在我的设计中我不能这样做,因为我一开始就错了。
@10676716 @GMB 先生给出了最棒的回答。
-- "top" table that stores the countries
create table countries (
country_id int primary key
name varchar(100)
);
-- the table that stores the divisions
create table divisions (
division_id int primary key,
country_id int references countries(country_id),
name varchar(100)
);
-- the table that stores the subdivisions
-- this corresponds to "table1" in your question
create table subdivisions (
subdivision_id int primary key,
division_id int references divisions(division_id),
name varchar(100)
);
-- the table that stores the reports
-- this corresponds to "table2" in your question
create table reports (
report_id int primary key,
division_id references divisions(division_id),
name varchar(100)
);
再次感谢专线小巴先生