1

I have a database with many tables, 4 of which are these

  1. Payment
  2. Credit Card
  3. Paypal
  4. Bitcoin

Credit Card attributes:

  • cardID (PK)
  • type
  • number
  • expireDate
  • ...

PayPal attributes:

  • paypalID (PK)
  • account
  • ...

Bitcoin attributes:

  • bitcoinID (PK)
  • ...

Payment Table attributes:

  • amount
  • ...
  • ...
  • cardID (FK)
  • paypalID (FK)
  • bitcoinID (FK)

A payment can only be paid by either a card/paypal/bitcoin so I am breaking 3rd normal form because if the client uses a card then I know that he didnt use paypal or bitcoin. How can I fix this so that I am not breaking 3rd normal Form.

  • Every PayPal transaction is a payment, but not every payment is a PayPal transaction. So the PayPal table should reference the appropriate payment, not the other way around. – IMSoP Apr 23 '15 at 00:14
  • the thing is that am storing there paypal, card, and bitcoin information because the payments are recurring aka monthly payments. So the paypal informations that I store is not a transaction its just the information needed to make a transaction. (hope that makes sense) – David Villarreal Apr 23 '15 at 00:21

1 Answers1

1

There isn't a completely clean way to do this today in SQL, because SQL platforms don't support assertions. (CREATE ASSERTION in the SQL standards) But you can design your tables to support sensible constraints, even without support for assertions.

Push the attributes that are common to all scheduled payments "up" into the table "scheduled_payments".

create table scheduled_payments (
  pmt_id integer primary key,
  pmt_amount numeric(14, 2) not null
    check (pmt_amount > 0),
  pmt_type char(1) not null
    check (pmt_type in ('b', 'c', 'p')),      -- (b)itcoin, (c)redit card, (p)aypal.
  other_columns char(1) not null default 'x', -- Other columns common to all payment types.
  unique (pmt_id, pmt_type)
);

-- Tables for Bitcoin and PayPal not shown, but they're very similar
-- to this table for credit cards.
create table credit_cards (
  pmt_id integer primary key,
  pmt_type char(1) not null default 'c'
    check (pmt_type = 'c'),
  foreign key (pmt_id, pmt_type) 
    references scheduled_payments (pmt_id, pmt_type),
  other_columns char(1) not null default 'x' -- Other columns unique to credit cards.
);

The primary key, not null, and check(...) constraints in "credit_cards" guarantee that every row will have a payment id number and a 'c'. The foreign key constraint guarantees that every row in "credit_cards" will reference a 'c' row in "scheduled_payments".

Community
  • 1
  • 1
Mike Sherrill 'Cat Recall'
  • 91,602
  • 17
  • 122
  • 185