【问题标题】: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?有没有办法在两个表之间建立关系,表一有 3 个唯一键,表二有 2 个唯一键在 SQL Server 中?
【发布时间】:2020-09-17 16:29:39
【问题描述】:

我想创建两个表之间的关系,这是我的表结构

表 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) 的那两个表之间创建关系。

所以当我想在table1中删除CountryCode = IDN和Division = A时,当table2包含CountryCode = IDN和Division = A时SQL会提示错误。

我曾尝试在这两个表之间创建关系,但 SQL Server 总是抛出此错误:

表 'table1' 中的列与现有的主键或唯一约束不匹配

谁能指导我如何在这两个表之间建立关系?

提前致谢

【问题讨论】:

  • AUTO_INCREMENT 不是 SQL Server 语法。你使用 MySQL 吗?你的设计在很多地方看起来也有问题。可能您应该为每个国家、部门和细分部门提供一个表,并分别使用“更高”表的外键。然后在报表的表格中只使用外键进行细分。
  • 感谢您的指正和建议。我会尝试重建我的数据库设计。 (Y) :D
  • 如果你在你的 table1 上的 CountryCode 和 Division 列上创建一个 uniq 索引就可以,但是如果你可以使用 GMB 的解决方案会更好

标签: sql sql-server tsql database-design foreign-keys


【解决方案1】:

你不能这样做。 SQL Server 需要外键目标上的唯一约束(或主键约束) - 并且您在源表中有重复项。

为此,您需要有一个单独的表来引用所有可能的(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 Server 等效项)使主键自动生成。

例如,下面是您将如何生成为细分显示的当前输出:

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,我从您那里学到了一些东西。我会执行你的建议。
  • 但是,如果实现为您的设计,我该如何选择以获得我想要的结果?因为我面临无法将表单动态输出加载为数据库设计的问题。
  • @user8124226:我在答案中添加了一个示例查询。
【解决方案2】:

正如 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

【讨论】:

  • 您好@8812269,感谢您的建议。我会再试一次,如果我的设计可行,我会告诉你。
【解决方案3】:

谢谢各位大佬的回答。

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

伟大的答案来自 @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)
);

再次感谢 GMB 先生。

【讨论】:

    猜你喜欢
    • 2019-06-24
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-11-24
    • 2023-03-19
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多