Deep down, in the guts of a relational database, its all rows and columns. That is the structure that a relational database is optimized to work with. Cursors work on individual rows at a time. Some operations create temporary tables (again, it needs to be rows and columns).
By working with only rows and returning only rows, the system is able to better deal with memory and network traffic.
As mentioned, this allows for certain optimizations to be done (indexes, joins, unions, etc...)
If one was to want a nested tree structure, this requires that one pulls all the data at once. Gone are the optimizations for the cursors on the database side. Likewise, the traffic over the network becomes one big burst that can take much longer than the slow trickle of row by row (this is something that is occasionally lost in today's web world).
Every language has arrays within it. These are easy things to work with and interface with. By using a very primitive structure, the driver between the database and program - no matter what language - can work in a common way. Once one starts adding trees, the structures in the language become more complex and more difficult to traverse.
It isn't that hard for a programing language to convert the rows returned into some other structure. Make it into a tree or a hash set or leave it as a list of rows that you can iterate over.
There is also history at work here. Transferring structured data was something ugly in the days of old. Look at the EDI format to get an idea of what you might be asking for. Trees also imply recursion - which some languages didn't support (the two most important languages of the old days didn't support recursion - recursion didn't enter Fortran until F90 and of the era COBOL didn't either).
And while the languages of today have support for recursion and more advanced data types, there isn't really a good reason to change things. They work, and they work well. The ones that are changing things are the nosql databases. You can store trees in documents in a document based one. LDAP (its actually oldish) is also a tree based system (though its probably not what you're after). Who knows, maybe the next thing in nosql databases will be one that returns back the query as a json object.
However, the 'old' relational databases... they're working with rows because thats what they're good at and everything can talk to them without trouble or translation.
- In protocol design, perfection has been reached not when there is nothing left to add, but when there is nothing left to take away.
From RFC 1925 - The Twelve Networking Truths
I'd use the auto-increment key. These keys are completely meaningless and in no way connected to the business or something in the environment that might change them, and this makes them much easier to use as foreign keys in other tables.
No matter how much the business is promising that some meaningful key will never change, or that the algorithm that is creating the keys will stay the same forever, these things might change, and when they do there will be problems if you didn't remember to set up cascading updates or something like that.
Best Answer
Foreign keys in your database enables data integrity, as you can't delete a parent row if there is a child row in another table.
While you can rely on the framework to handle data for you, the framework will not enable data integrity and you will eventually end up with orphan rows in your database.
So, my advice is: design the database properly in order to preserve data.