views:

1085

answers:

6

A couple of recent questions discuss strategies for naming columns, and I was rather surprised to discover the concept of embedding the notion of foreign and primary keys in column names. That is

select t1.col_a, t1.col_b, t2.col_z
from t1 inner join t2 on t1.id_foo_pk = t2.id_foo_fk

I have to confess I have never worked on any database system that uses this sort of scheme, and I'm wondering what the benefits are. The way I see it, once you've learnt the N principal tables of a system, you'll write several orders of magnitude more requests with those tables.

To become productive in development, you'll need to learn which tables are the important tables, and which are simple tributaries. You'll want to commit an good number of column names to memory. And one of the basic tasks is to join two tables together. To reduce the learning effort, the easiest thing to do is to ensure that the column name is the same in both tables:

select t1.col_a, t1.col_b, t2.col_z
from t1 inner join t2 on t1.id_foo = t2.id_foo

I posit that, as a developer, you don't need to be reminded that much about which columns are primary keys, which are foreign and which are nothing. It's easy enough to look at the schema if you're curious. When looking at a random

tx inner join ty on tx.id_bar = ty.id_bar

... is it all that important to know which one is the foreign key? Foreign keys are important only to the database engine itself, to allow it to ensure referential integrity and do the right thing during updates and deletes.

What problem is being solved here? (I know this is an invitation to discuss, and feel free to do so. But at the same time, I am looking for an answer, in that I may be genuinely missing something).

+7  A: 

I agree with you. Putting this information in the column name smacks of the crappy Hungarian Notation idiocy of the early Windows days.

Paul Tomblin
A: 

I agree with you--I take a different approach that I have seen recommended in many corporate environments:

Name columns in the format TableNameFieldName, so if I had a Customer table and UserName was one of my fields, the field would be called CustomerUserName. That means that if I had another table called Invoice, and the customer's user name was a foreign key, I would call it InvoiceCustomerUserName, and when I referenced it, I would call it Invoice.CustomerUserName, which immediately tells me which table it's in.

Also, this naming helps you to keep track of the tables your columns are coming from when you're joiining.

I only use FK_ and PK_ in the ACTUAL names of the foreign and primary keys in the DBMS.

Ed Altorfer
Wouldn't it be Invoice.InvoiceCustomerUserName? And this is in danger of being worse than the type tags...Invoice.UserName = Customer.UserName seems sufficiently clear to me.
Jonathan Leffler
Sorry, this is ghastly. Simply ghastly. It looks like the sort of "cleverness" that obviates the need for table aliases. Almost as bad as the place I worked where table names were prefixed T_ and columns C_ (views and indexes got prefixes too...)
Mike Woodhouse
That is just redundant. You have to reference the table name ANYWAYS when you do a join. Additionally, username is *NOT* a good primary key (eg, invoice having CustomerUserName is clearer than invoice having UserName, but both are wrong). ..JOIN user ON invoice.userid = user.userid is very clear
gregmac
A: 

I used "fk_" on the front end of any foreign keys for a table mostly because it helped me keep it straight when developing the DB for a project at my shop. Having not done any DB work in the past, this did help me. In hindsight, perhaps I didn't need to do that but it was three characters tacked onto some column names so I didn't sweat it.

Being a newcomer to writing DB apps, I may have made a few decisions which would make a seasoned DB developer shudder, but I'm not sure the foreign key thing really is that big a deal. Again, I guess it is a difference in viewpoint on this issue and I'll certainly take what you've written and cogitate on it.

Have a good one!

itsmatt
+1  A: 

I only use the tablename with an Id suffix for the primary key, e.g. CustomerId, and foreign keys referencing that from other tables would also be called CustomerId. When you reference in the application it becomes obvious the table from the object properties, e.g. Customer.TelephoneNumber, Customer.CustomerId, etc.

Turnkey
Why couldn't CustomerId be Customer.Id? Then any table with a CustomerId column clearly has a foreign key relationship to Customer.
Mike Woodhouse
I can see how you might think it was redundant but I think it looks better to have Customer.CustomerId = Order.CustomerId rather than Customer.Id = Order.CustomerId.
WW
+5  A: 

I agree with you that the foreign key column in a child table should have the same name as the primary key column in the parent table. Note that this permits syntax like the following:

SELECT * FROM foo JOIN bar USING (foo_id);

The USING keyword assumes that a column exists by the same name in both tables, and that you want an equi-join. It's nice to have this available as shorthand for the more verbose:

SELECT * FROM foo JOIN bar ON (foo.foo_id = bar.foo_id);

Note, however, there are cases when you can't name the foreign key the same as the primary key it references. For example, in a table that has a self-reference:

CREATE TABLE Employees (
  emp_id INT PRIMARY KEY,
  manager_id INT REFERENCES Employees(emp_id)
);

Also a table may have multiple foreign keys to the same parent table. It's useful to use the name of the column to describe the nature of the relationship:

CREATE TABLE Bugs (
  ...
  reported_by INT REFERENCES Accounts(account_id),
  assigned_to INT REFERENCES Accounts(account_id),
  ...
);

I don't like to include the name of the table in the column name. I also eschew the obligatory "id" as the name of the primary key column in every table.

Bill Karwin
+5  A: 

I've espoused most of the ideas proposed here over the 20-ish years I've been developing with SQL databases, I'm embarrassed to say. Most of them delivered few or none of the expected benefits and were with hindsight, a pain in the neck.

Any time I've spent more than a few hours with a schema I've fairly rapidly become familiar with the most important tables and their columns. Once it got to a few months, I'd pretty much have the whole thing in my head.

Who is all this explanation for? Someone who only spends a few minutes with the design isn't going to be doing anything serious anyway. Someone who plans to work with it for a long time will learn it if you named your columns in Sanskrit.

Ignoring compound primary keys, I don't see why something as simple as "id" won't suffice for a primary key, and "_id" for foreign keys.

So a typical join condition becomes customer.id = order.customer_id.

Where more than one association between two tables exists, I'd be inclined to use the association rather than the table name, so perhaps "parent_id" and "child_id" rather than "parent_person_id" etc

Mike Woodhouse