简体   繁体   English

如何在2个不同的表中强制使用不同的主键?

[英]How to enforce different primary keys in 2 different tables?

I may be missing something simple here but I can't seem to find an answer. 我可能在这里错过了一些简单的东西,但似乎找不到答案。

I have two entities that are inherited from another and I want to enforce that the child entities cannot have the same key as each other in the database rather than with queries. 我有两个从另一个继承的实体,我想强制要求子实体在数据库中不能具有彼此相同的键,而不能与查询具有相同的键。

For example I want credit card or paypal to have the same primary key as payment, but I only want that to be in either credit card or paypal, not both. 例如,我希望信用卡或贝宝具有与付款相同的主键,但是我只希望它既包含信用卡又包含贝宝,而不是同时存在于两者中。 So a payment is a credit card or a paypal but not both. 因此,付款是信用卡或支付宝,但不能同时使用两者。

I though it would be simple constraint, something like: 我虽然是简单的约束,但类似:

check (cc.transaction != pp.transaction)

But this doesn't seem to work in mysql workbench. 但这在mysql工作台中似乎不起作用。 Any ideas? 有任何想法吗?

I have found out that in fact checks don't work at all in mySQL, and so I need to use a trigger, but there it no way to just cancel the insert so it has to throw an error to exit instead. 我发现实际上检查在mySQL中根本不起作用,因此我需要使用触发器,但是没有办法只取消插入操作,因此必须抛出错误才能退出。 I am using mySQL Workbench which supports triggers but it will not accept any I try, eg: 我正在使用支持触发器的mySQL Workbench,但不接受我尝试的任何触发器,例如:

CREATE DEFINER = CURRENT_USER TRIGGER `ddi`.`tcredit_card_BEFORE_INSERT` 
BEFORE INSERT ON `tcredit_card` FOR EACH ROW
BEGIN   
    IF EXISTS (SELECT Paypal_ID FROM tPaypal WHERE Paypal_ID = NEW.Card_ID) THEN 
    SIGNAL SQLSTATE '02000' SET MESSAGE_TEXT = 'Cannot have multiple payments.';
    END IF;
END;

It always says there's and error no matter what I do, including attempting to change the delimiter which also come up as an error. 无论我做什么,它总是说存在和错误,包括尝试更改定界符,这也会出现错误。 Now short of smashing the spinning jenny and using paper records and a horse and cart surely there must be a way for this to work? 现在,除了砸碎旋转的珍妮,使用纸质记录和一匹马车之外,肯定有某种方法可以起作用吗? (without changing the db schema) (无需更改数据库架构)

You can have a super-type and sub-types arrangement in the database and it's really easy to keep them separate. 您可以在数据库中具有超类型和子类型的排列,将它们分开很容易。 Just declare the subtype as part of the super key then enforce type values in the sub-tables. 只需将子类型声明为超级键的一部分,然后在子表中强制使用类型值即可。

Whenever possible, let the constraints and checks built into the underlying system enforce whatever design you implement. 只要有可能,就让底层系统中内置的约束和检查强制实施您实现的任何设计。

create table Super(
    ID  int not null auto_increment,
    SubType char( 1 ) not null check( SubType in( 'A', 'B' ) ),
    ...
    constraint PK_Super primary key( ID, SubType )
);

create table subA(
    SubAID  int not null,
    SubType char( 1 ) not null default 'A' check( SubType = 'A' ),
    ... -- data specific to Type = A
    constraint PK_SubA primary key( SubAID, SubType ),
    constraint FK_SubA_Super foreign key( SubAID, SubType )
        references Super( ID, SubType )
);

create table subB(
    SubBID  int not null,
    SubType char( 1 ) not null default 'B' check( SubType = 'B' ),
    ... -- data specific to Type = B
    constraint PK_SubB primary key( SubBID, SubType ),
    constraint FK_SubB_Super foreign key( SubBID, SubType )
        references Super( ID, SubType )
);

It may seem redundant to make Super.SubType part of the PK since Super.ID is a surrogate key all by itself, but look at what you get. 将Super.SubType包含在PK中似乎是多余的,因为Super.ID本身就是代理密钥,但请看您得到了什么。

  • The Super table contains the data common to all subtypes (transaction date, type (credit/debit), amount, etc.). 超级表包含所有子类型(交易日期,类型(贷方/借方),金额等)通用的数据。
  • With the proper constraint (you could use another table with defined subtypes) no entry is possible in Super that is not a properly defined subtype. 在适当的约束下(您可以使用具有定义的子类型的另一个表),在Super中不能输入不是正确定义的子类型的条目。
  • The subtype value tells you which sub-table contains the type-specific data. 子类型值告诉您哪个子表包含特定于类型的数据。
  • No entry can be made in a sub-table that is not first made in the super table. 不能在超级表中未首先创建的子表中进行任何输入。 And, once defined, the subtype cannot be changed -- entries in A can have nothing but 'A' in SubType field. 并且,一旦定义了子类型,就无法更改-A中的条目在SubType字段中只能有“ A”。 Nor, once a FK connection is made, can an 'A' entry in Super be changed to 'B' or vice versa. 一旦建立FK连接,Super中的“ A”条目也不能更改为“ B”,反之亦然。

If you want to enforce this logic in the database, you might need another table. 如果要在数据库中强制执行此逻辑,则可能需要另一个表。

How about this, if I've understood your problem: 如果我了解您的问题,该怎么办:

  • payment(paymentID, date, amount) 付款(paymentID,日期,金额)
  • paymentType(paymentTypeID, paymentID) paymentType(paymentTypeID,paymentID)
  • creditCardPaymentType(creditCardPaymentTypeID, paymentTypeID, cc#, CVV2, expiration) creditCardPaymentType(creditCardPaymentTypeID,paymentTypeID,cc#,CVV2,到期)
  • paypalPaymentType(paypalPaymentTypeID, paymentTypeID, paypalname, paypalotherinfowhatever) paypalPaymentType(paypalPaymentTypeID,paymentTypeID,paypalname,paypalotherinfo等等)

And then make paymentType(paymentID) unique. 然后使paymentType(paymentID)唯一。

But it could be more performant to enforce the logic in the application. 但是在应用程序中执行逻辑可能会更有性能。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM