在子类型表中将单个属性同时用作主键和外键

时间:2018-07-06 07:38:06

标签: sql sql-server foreign-keys primary-key

我有一个名为Card的超类型表(来自ERD),该表有两个子类型:Credit CardDebit Card。我的表Primary Key中有一个Card,名为CardID

如果我将Primary Key的{​​{1}}分别作为CardCredit Card的外键和主键,是否正确?

如何将超类型表的主键导入其子类型(代码)?我只是这样做吗?

Debit Card

3 个答案:

答案 0 :(得分:2)

如果信用卡表的结构与借记卡表的结构有很大不同,我认为按您所描述的方式来处理密钥是有意义的。您是否需要权衡这种解决方案是否比仅拥有一张包含信用卡或借记卡所有字段的卡表更好。

您编写查询的方式就像说您有两个具有相同名称的不同列一样,如GuidoG所述。您想要这样的东西:

CREATE TABLE [Credit Card] (
    CreditCardNumber varchar(50) NOT NULL Primary Key,
    ....(other cols)....,
    CONSTRAINT FK_CreditCard_Card Foreign Key (CreditCardNumber) REFERENCES Card(CardID)
)

我想补充一点,您对最佳解决方案的了解可能与“多态关联”密切相关,请仔细检查一下。

回应您的评论:您所说的话中唯一 not 正确的是“ but”一词。您似乎已经想到,如果一个列同时是PK和FK,那是“奇怪的”。它不是。它们是完全不相关的两件事,SQL Server不在乎。 PK确保此列中的每一行都有不同的值。 FK确保该值必须存在于另一个表的一列的可能值中。完全没有冲突;除了可能的哲学/设计冲突外,这当然只在您的脑海中发生(而不是sql server的结构),而我的响应(以及许多其他响应)已经涵盖了。

答案 1 :(得分:1)

请参见Doc\SQL\T-SQL

CREATE TABLE [Credit Card] (
    CreditCardNumber varchar(50) NOT NULL Primary Key,
    Foreign Key (CreditCardNumber) REFERENCES Card(CardID)
)

答案 2 :(得分:1)

我想你想要这样的东西

create table dbo.[Credit Card] (
  CreditCardNumber varchar(50) not null,
  other columns ...

  constraint PK_CreditCardNumber primary key (CreditCardNumber),
  constraint FK_CreditCard_Card foreign key (CreditCardNumber) references Card(CardID)
)

仅当表CardID中的列Card与表CreditCardNumber中的列Credit Card具有相同的定义时,此方法才有效
仅从名称来看可能不是这种情况吗?

在大多数情况下,最好使用Discrimator字段和一个表。
例如

create table dbo.Card (
   CardNumber varchar(50) not null,
   CardType char(1) not null check (CardType in ('C', 'D')),

   CreditCardColumn1 varchar(50) null,
   CreditCardColumn2 varchar(50) null,

   DebitCardColumn1 varchar(50) null,

   constraint PK_CardNumber primary key (CardNumber),
)

检查约束将确保仅CD可以存储在此列中。
此表必须同时填写信用卡和Debet卡两栏。 您为每种类型编写的查询应该不同,表将始终相同

现在,当您只需要使用所有信用卡时

select c.CardNumber,
       c.CardType,
       c.CreditCardColumn1,
       c.CreditCardColumn2
from   dbo.Card c
where  CardType = 'C'

对于所有借记卡都可以

select c.CardNumber,
       c.CardType,
       c.DebitCardColumn1
from   dbo.Card c
where  CardType = 'D'