简体   繁体   中英

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. 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. I am using mySQL Workbench which supports triggers but it will not accept any I try, eg:

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.

  • 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.
  • 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. Nor, once a FK connection is made, can an 'A' entry in Super be changed to 'B' or vice versa.

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)
  • paymentType(paymentTypeID, paymentID)
  • creditCardPaymentType(creditCardPaymentTypeID, paymentTypeID, cc#, CVV2, expiration)
  • paypalPaymentType(paypalPaymentTypeID, paymentTypeID, paypalname, paypalotherinfowhatever)

And then make paymentType(paymentID) unique.

But it could be more performant to enforce the logic in the application.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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