在 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 列。

SQL fiddle

谢谢大家的回答。

但是在我的设计中我不能这样做,因为我一开始就错了。

@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)
);

再次感谢专线小巴先生