Обсуждение: Redefining an existing Table Schema for Foreign Key Constraint - Question

Поиск
Список
Период
Сортировка

Redefining an existing Table Schema for Foreign Key Constraint - Question

От
Brian714
Дата:
Hello everyone,

I am new to the forum and fairly new to databases (particularly PostgreSQL).
I have done some searching on the internet and can't really get a hold of an
answer to my question. So here it goes:

I am working on a Customer Purchasing-based project where I must use a
database with existing customer data. The database currently follows the
following schema for two tables:

Creditcards Table
id:integer -- primary key
credit_card_number:varchar(16)
name_on_card:varchar(100)
expiration:date

Customers Table
id:integer -- primary key
first_name:varchar(50)
last_name:varchar(50)
credit_card_number:varchar(16)
address:varchar(200)
email:varchar(50)
password:varchar(20)

Currently, the database contains thousands of records in the Customers and
Creditcards tables. I would like to re-define the Customers table to follow
the following schema:

Customers Table
id:integer -- primary key
first_name:varchar(50)
last_name:varchar(50)
cc_id:integer references Creditcards.id
address:varchar(200)
email:varchar(50)
password:varchar(20)

As you can see, I would like to convert the column that used to be
"credit_card_number" from the Customers table and turn it into a "cc_id"
which is an integer that references the column "id" from the table
Creditcards.

I would like for the Customers.cc_id to match with a Creditcards.id that has
the same credit_card_number.

Does anyone know of a script that I can use to do this? Am I supposed to use
Triggers? How can this be done safely. I would like for the data to be
consistent. Thank you guys in advance.
--
View this message in context:
http://www.nabble.com/Redefining-an-existing-Table-Schema-for-Foreign-Key-Constraint---Question-tp20294223p20294223.html
Sent from the PostgreSQL - general mailing list archive at Nabble.com.


Re: Redefining an existing Table Schema for Foreign Key Constraint - Question

От
brian
Дата:
Brian714 wrote:
> Hello everyone,
>
> I am new to the forum and fairly new to databases (particularly PostgreSQL).
> I have done some searching on the internet and can't really get a hold of an
> answer to my question. So here it goes:
>
> I am working on a Customer Purchasing-based project where I must use a
> database with existing customer data. The database currently follows the
> following schema for two tables:
>
> Creditcards Table
> id:integer -- primary key
> credit_card_number:varchar(16)
> name_on_card:varchar(100)
> expiration:date
>
> Customers Table
> id:integer -- primary key
> first_name:varchar(50)
> last_name:varchar(50)
> credit_card_number:varchar(16)
> address:varchar(200)
> email:varchar(50)
> password:varchar(20)
>
> Currently, the database contains thousands of records in the Customers and
> Creditcards tables. I would like to re-define the Customers table to follow
> the following schema:
>
> Customers Table
> id:integer -- primary key
> first_name:varchar(50)
> last_name:varchar(50)
> cc_id:integer references Creditcards.id
> address:varchar(200)
> email:varchar(50)
> password:varchar(20)
>
> As you can see, I would like to convert the column that used to be
> "credit_card_number" from the Customers table and turn it into a "cc_id"
> which is an integer that references the column "id" from the table
> Creditcards.
>
> I would like for the Customers.cc_id to match with a Creditcards.id that has
> the same credit_card_number.

This should do it:


ALTER TABLE Customers ADD COLUMN cc_id INTEGER;

UPDATE Customers AS c SET cc_id = Creditcards.id FROM Creditcards WHERE
c.credit_card_number = Creditcards.credit_card_number;


(I'm not sure of the best way to use table aliases in the above statement.)


ALTER TABLE Customers DROP COLUMN credit_card_number;

ALTER TABLE Customers ADD CONSTRAINT fk_credit_card_id FOREIGN KEY
(cc_id) REFERENCES Creditcards (id) ON DELETE CASCADE;

I think those last two can be rolled into one statement but it doesn't
hurt to separate them.

I'm assuming here that Creditcards.id is a SERIAL type. Also, you might
want to read up on foreign keys and decide on the best ON DELETE
scenario for your situation.

> I would like for the data to be consistent.

Indeed ;-)

Re: defining an existing Table Schema for Foreign Key Constraint - Question

От
Sam Mason
Дата:
On Sun, Nov 02, 2008 at 02:30:45PM -0800, Brian714 wrote:
> I would like to convert the column that used to be
> "credit_card_number" from the Customers table and turn it into a "cc_id"
> which is an integer that references the column "id" from the table
> Creditcards.
[...]
> Does anyone know of a script that I can use to do this? Am I supposed to use
> Triggers? How can this be done safely. I would like for the data to be
> consistent. Thank you guys in advance.

If you just want to move the data across all you need is a couple of SQL
statements:

  ALTER TABLE customers
    ADD COLUMN cc_id INTEGER REFERENCES creditcards (id);

  UPDATE customers c SET cc_id = d.id
    FROM creditcards d
    WHERE c.credit_card_number = d.credit_card_number;

The first creates the new "cc_id" column in the customers table and the
second moves the data across.  For this to be valid, you really need
to make sure that there is only one "id" number for each credit card
number, the following is a standard way of doing this:

  SELECT credit_card_number, COUNT(*)
  FROM creditcards
  GROUP BY credit_card_number
  HAVING COUNT(*) > 1;

If you already have a UNIQUE constraint on the "credit_card_number"
column then this will be being enforced by the database already and
the check is redundant.  Another check would be that all the customers
credit cards are already in the "creditcards" table:

  SELECT c.*
  FROM customers c
    LEFT JOIN creditcards d ON c.credit_card_number = d.credit_card_number
  WHERE c.credit_card_number IS NOT NULL
    AND d.credit_card_number IS NULL;

I.e. give me all the customers where they have a credit card number yet
we can't find a matching entry.


On a slightly tangential note, why not use the "credit_card_number"
as the primary key in the creditcards table?  It looks like the
perfect example of a "natural key" and you wouldn't have to change the
"customers" table at all, except maybe to let the database check that
everything matches automatically:

  ALTER TABLE creditcards
    ADD CONSTRAINT creditcards_ccnum_uniq
      UNIQUE (credit_card_number);

  ALTER TABLE customers
    ADD FOREIGN KEY (credit_card_number)
      REFERENCES creditcards (credit_card_number);

After you've made sure everything still works, you may want to drop
the existing "id" out of the creditcards table and upgrade the unique
constraint to a full primary key:

  ALTER TABLE creditcards
    DROP CONSTRAINT creditcards_pkey,
    DROP CONSTRAINT creditcards_ccnum_uniq,
    ADD PRIMARY KEY (credit_card_number),
    DROP COLUMN id;

I'm a strong believer in natural keys at the moment, but it's somewhat
a religious battle!  A search on natural keys or surrogate keys should
give a reasonable view of the battle field.  Which way you go is a
design decision with trade-offs either way, but as you said you were
somewhat new to databases I thought a couple of examples could be
useful---I also get to think I've done something productive today!

Hum, I seem to have completely forgotten about triggers.  They are
useful if you want to automatically keep the customers table up-to-date
while maintaining the existing columns in the table.  Although, in this
case, it may be easier to use a "view" to present the new table designs
in a compatible way to how they were before, if you've got control over
the code that accesses these tables that may not even be needed.

Hope that helps!


  Sam

Re: Redefining an existing Table Schema for Foreign Key Constraint - Question

От
Harald Fuchs
Дата:
In article <20294223.post@talk.nabble.com>,
Brian714 <bndang@uci.edu> writes:

> Currently, the database contains thousands of records in the Customers and
> Creditcards tables. I would like to re-define the Customers table to follow
> the following schema:

> Customers Table
> id:integer -- primary key
> first_name:varchar(50)
> last_name:varchar(50)
> cc_id:integer references Creditcards.id
> address:varchar(200)
> email:varchar(50)
> password:varchar(20)

> As you can see, I would like to convert the column that used to be
> "credit_card_number" from the Customers table and turn it into a "cc_id"
> which is an integer that references the column "id" from the table
> Creditcards.

This is the usual 1:n relationship, but I think you got it backwards.
There are two questions to ask:
1. Are there customers with more than one credit card?
2. Are there credit cards owned by more than one customer?

Re: Redefining an existing Table Schema for Foreign Key Constraint - Question

От
Michelle Konzack
Дата:
Hallo Harald,

Am 2008-11-03 13:41:52, schrieb Harald Fuchs:
> In article <20294223.post@talk.nabble.com>,
> Brian714 <bndang@uci.edu> writes:
> > Customers Table
> > id:integer -- primary key
> > first_name:varchar(50)
> > last_name:varchar(50)
> > cc_id:integer references Creditcards.id
> > address:varchar(200)
> > email:varchar(50)
> > password:varchar(20)
> This is the usual 1:n relationship, but I think you got it backwards.
> There are two questions to ask:
> 1. Are there customers with more than one credit card?

This could be a problem for the above table...

> 2. Are there credit cards owned by more than one customer?

CreditCards are personaly and sometimes (in France) I need an ID card to
prove, that I am the holder...

So how can one credit card can have more then one owner?

Thanks, Greetings and nice Day/Evening
    Michelle Konzack
    Systemadministrator
    24V Electronic Engineer
    Tamay Dogan Network
    Debian GNU/Linux Consultant


--
Linux-User #280138 with the Linux Counter, http://counter.li.org/
##################### Debian GNU/Linux Consultant #####################
Michelle Konzack   Apt. 917                  ICQ #328449886
+49/177/9351947    50, rue de Soultz         MSN LinuxMichi
+33/6/61925193     67100 Strasbourg/France   IRC #Debian (irc.icq.com)

Вложения

Re: Redefining an existing Table Schema for Foreign Key Constraint - Question

От
Harald Fuchs
Дата:
In article <20081106213736.GB25016@tamay-dogan.net>,
Michelle Konzack <linux4michelle@tamay-dogan.net> writes:

> Hallo Harald,
> Am 2008-11-03 13:41:52, schrieb Harald Fuchs:
>> In article <20294223.post@talk.nabble.com>,
>> Brian714 <bndang@uci.edu> writes:
>> > Customers Table
>> > id:integer -- primary key
>> > first_name:varchar(50)
>> > last_name:varchar(50)
>> > cc_id:integer references Creditcards.id
>> > address:varchar(200)
>> > email:varchar(50)
>> > password:varchar(20)
>> This is the usual 1:n relationship, but I think you got it backwards.
>> There are two questions to ask:
>> 1. Are there customers with more than one credit card?

> This could be a problem for the above table...

>> 2. Are there credit cards owned by more than one customer?

> CreditCards are personaly and sometimes (in France) I need an ID card to
> prove, that I am the holder...

> So how can one credit card can have more then one owner?

That's exactly why I told you "I think you got it backwards".
You need a cust_id column in your CreditCards table, not a cc_id
column in your Customers table.