I’m starting a new project and would like to get my table and column names right. For example I’ve always used plural in table names but recently learned singular is correct.
So if I have a table user and I have products that only the user will have,
should the table be named user_product or just product? This is a one-to-many relationship.
And if I have several product descriptions for each product, would it be user_product_description or product_description or just description? With the right foreign keys set. Naming it only description would be problematic since I could also have user descriptions or account descriptions or whatever.
What if I want a pure relational table (many-to-many) with only two columns? user_stuff or maybe something like rel_user_stuff? And if the first one, what would distinguish this from, for example, user_product?
Table • Name
Yes. Plural in the table names are a sure sign of someone who has not read any of the standard materials and has no knowledge of database theory.
Some of the wonderful things about Standards are:
debate them.
The standard table name refers to each row in the table, which is used in the all verbiage, not the total content of the table (we know that the
Customertable contains all the Customers).Relationship, Verb Phrase
In genuine Relational Databases that have been modelled (as opposed to pre-1970’s Record Filing Systems [characterised by
Record IDswhich are implemented in an SQL database container for convenience):[**Diagram_A**][Diagram_A]
Of course, the relationship is implemented in SQL as a
CONSTRAINT FOREIGN KEYin the child table (more, later). Here is the Verb Phrase (in the model), the Predicate that it represents (to be read from the model), and the FK Constraint Name:Table • Language
However, when describing the table, particularly in technical language such as the Predicates, or other documentation, use singular and plurals as they naturally in the English language. Keeping in mind the table is named for the single row (relation) and the language refers to each derived row (derived relation):
not
(That is not a naming-convention question; that is a db design question.) It doesn’t matter if
user::productis 1::n. What matters is whetherproductis a separate entity and whether it is an Independent Table, ie. it can exist on its own. Thereforeproduct, notuser_product.And if
productexists only in the context of anuser, ie. it is a Dependent Table, thereforeuser_product.[**Diagram_B**][Diagram_B]
That’s right. Either
user_product_descriptionxorproduct_descriptionwill be correct, based on the above. It is not to differentiate it from otherxxxx_descriptions, but it is to give the name a sense of where it belongs, the prefix being the parent table.Hopefully all the tables in the relational database are pure relational, normalised tables. There is no need to identify that in the name (otherwise all the tables will be
rel_something).If it contains only the PKs of the two parents (which resolves the logical n::n relationship that does not exist as an entity at the logical level, into a physical table), that is an Associative Table. Yes, typically the name is a combination of the two parent table names.
Note that is such cases the Verb Phrase applies to, and is read as, from parent to parent, ignoring the child table, because its only purpose in life is to relate the two parents.
[**Diagram_C**][Diagram_C]
If it is not an Associative Table (ie. in addition to the two PKs, it contains data), then name it appropriately, and the Verb Phrases apply to it, not the parent at the end of the relationship.
[**Diagram_D**][Diagram_D]
If you end up with two
user_producttables, then that is a very loud signal that you have not normalised the data. So go back a few steps and do that, and name the tables accurately and consistently. The names will then resolve themselves.Naming Convention
What you are doing is very important, and it will affect the ease of use and understanding at every level. So it is good to get as much understanding as possible at the outset. The relevance of most of this will not be clear, until you start coding in SQL.
Case is the first item to address. All caps is unacceptable. Mixed case is normal, especially if the tables are directly accessible by the users. Refer my data models. Note that when the seeker is using some kind of NonSQL, that has only lowercase, I give that, in which case I include underscores (as per your examples).
Maintain a data focus, not an application or usage focus. We have had Open Architecture since 1984, and databases are supposed to be independent of the apps that use them.
That way, as they grow, and more than the one app uses them, the naming will remain meaningful, and need no correction. (Databases that are completely embedded in a single app are not databases.) Name the data elements as data, only.
Be very considerate, and name tables and columns very accurately. Do not use
UpdatedDateif it is aDATETIMEdatatype, useUpdatedDtm. Do not use_descriptionif it contains a dosage.It is important to be consistent across the database. Do not use
NumProductin one place to indicate number of Products andItemNoorItemNumin another place to indicate number of Items. UseNumSomethingfor numbers-of, andSomethingNoorSomethingIdfor identifiers, consistently.Do not prefix the column name with a table name or short code, such as
user_first_name. SQL already provides for the tablename as a qualifier:Exceptions:
The first exception is for PKs, they need special handling because you code them in joins, all the time, and you want keys to stand out from data columns. Always use
user_id, neverid.user_idis the column that identifies an user, not theidof theusertable.user_producttable will have anuser_idas a component of its PK(user_id, product_no).idon many tables, it is easy get mixed up in SQL coding. Second, anyone other that the initial coder has no idea what he was trying to do. Both of which are easy to prevent, if the key columns are treated as above.The second exception is where there is more than one FK referencing the same parent table table, carried in the child. As per the Relational Model, use Role Names to differentiate the meaning or usage, eg.
AssemblyCodeandComponentCodefor twoPartCodes. And in that case, do not use the undifferentiatedPartCodefor one of them. Be precise.Diagram_E
Prefix
Where you have more than say 100 tables, prefix the table names with a Subject Area:
REF_for Reference tablesOE_for the Order Entry cluster, etc.Only at the physical level, not the logical (it clutters the model).
Suffix
Never use suffixes on tables, and always use suffixes on everything else. That means in the logical, normal use of the database, there are no underscores; but on the administrative side, underscores are used as a separator:
_VView (with the mainTableNamein front, of course)_fkForeign Key (the constraint name, not the column name)_cacCache_segSegment_trTransaction (stored proc or function)_fnFunction (non-transactional), etc.The format is the table or FK name, an underscore, and action name, an underscore, and finally the suffix.
This is really important because when the server gives you an error message:
____
blah blah blah error on object_nameyou know exactly what object was violated, and what it was trying to do:
____
blah blah blah error on Customer_Add_trForeign Keys (the constraint, not the column). The best naming for a FK is to use the Verb Phrase (minus the "each" and the cardinality).
Customer_Initiates_SalesOrder_fkPart_Comprises_Component_fkPart_IsConsumedIn_Assembly_fkUse the
Parent_Child_fksequence, notChild_Parent_fkis because (a) it shows up in the correct sort order when you are looking for them and (b) we always know the child involved, what we are guessing at is, which parent. The error message is then delightful:____
Foreign key violation on Vendor_Offers_PartVendor_fk.That works well for people who model their data, where the Verb Phrases have been identified. For the rest, the record filing systems, etc, use
Parent_Child_fk.UUnique, or_for non-uniqueCClustered, or_for non-clustered_separatorFor the remainder:
– If the key is one column or a very few columns:
____
ColumnNames____
PKPrimary Key (as per model)____
AK[*n*]Alternate Key (IDEF1X term)Note that the table name is not required in the index name, because it always shows up as
table_name.index_name.So when
Customer.UC_CustomerIdorProduct.U__AKappears in an error message, it tells you something meaningful. When you look at the indices on a table, you can differentiate them easily.Order Entry & Inventory with Standard-compliant Addresses
Simple inter-office Bulletin system for PHP/MySQL
Sensor Monitoring with full Temporal capability
Answers to Questions
That cannot be reasonably answered in the comment space.
There are two major problems in your comment:
You declare your example to be "the most trivial", however, it is anything but. With that sort of contradiction, I am uncertain if you are serious, if technically capable.
That "trivial" speculation has several gross Normalisation (DB Design) errors.
Until you correct those, they are unnatural and abnormal, and they do not make any sense. You might as well name them abnormal_1, abnormal_2, etc.
You have "suppliers" who do not supply anything; circular references (illegal, and unnecessary); customers buying products without any commercial instrument (such as Invoice or SalesOrder) as a basis for the purchase (or do customers "own" products?); unresolved many-to-many relationships; etc.
Once that is Normalised, and the required tables are identified, their names will become obvious. Naturally.
In any case, I will try to service your query. Which means I will have to add some sense to it, not knowing what you meant, so please bear with me. The gross errors are too many to list, and given the spare specification, I am not confident I have corrected them all.
I will assume that if the product is made up of components, then the product is an assembly, and the components are used in more than one assembly.
Further, since "Supplier sells zero-to-many Components", that they do not sell products or assemblies, they sell only components.
Speculation vs Normalised Model
In case you are not aware, the difference between square corners (Independent) and round corners (Dependent) is significant, please refer to the IDEF1X Notation link. Likewise the solid lines (Identifying) vs dashed lines (Non-identifying).
(Or, AssemblyComponent, for those who realise that one fact identifies the other)
Now that I have resolved the tables, I don’t understand your problem. Perhaps you can post a specific question.
Predicate
Assuming there are no Normalisation errors,
User likes Productis a predicate, not a table. Do not confuse them. Refer to my Answer, where it relates to Subjects, Verbs, and Predicates, and my response to Larry immediately above.Each table contains a set of Facts (each row is a Fact). Predicates (or propositions), are not Facts, they may or may not be true.
The Relational Model is based on First Order Predicate Calculus (more commonly known as First Order Logic). A Predicate is a single-clause sentence in simple, precise English, that evaluates to true or false.
Further, each table represents, or is the implementation of, many Predicates, not one.
A query is a test of a Predicate (or a number of Predicates, chained together) that results in true (the Fact exists) or false (the Fact does not exist).
Thus tables should be named, as detailed in my Answer (naming conventions), for the row, the Fact, and the Predicates should be documented (by all means, it is part of the database documentation), but as a separate list of Predicates.
This is not a suggestion that they are not important. They are very important, but I won’t write that up here.
Quickly, then. Since the Relational Model is founded on FOPC, the entire database can be said to be a set of FOPC declarations, a set of Predicates. But (a) there are many types of Predicates, and (b) a table does not represent one Predicate (it is the physical implementation of many Predicates, and of different types of Predicates).
Therefore naming the table for "the" Predicate that it "represents" is an absurd concept.
The "theoreticians" are aware of only a few Predicates, they do not understand that since the RM was founded on the FOL, the entire database is a set of Predicates, and of different types.
And of course, they choose absurd ones from the few that they do know:
EXISTING_PERSON;PERSON_IS_CALLED. If it were not so sad, it would be hilarious.Note also that the Standard or atomic table name (naming the row) works brilliantly for all the verbiage (including all Predicates attached to the table). Conversely, the "table represents predicate" name cannot, which is fine for the "theoreticians", who understand very little about Predicates, but not otherwise.
The Predicates that are relevant to the data model, are expressed in the model, they are of two orders.
The first set is diagrammatic, not text: the notation itself. These include various Existential; Constraint-oriented; and Descriptor (attributes) Predicates.
The second set is those that form relationships between Facts. This is the relation line. The Verb Phrase (detailed above) identifies the Predicate, the proposition, that has been implemented (which can be tested via query). One cannot get more explicit than that.
Therefore, to one who is fluent in Standard data models, all the Predicates that are relevant, are documented in the model. They do not need a separate list of Predicates (but the users, who cannot ‘read’ everything from the data model, do!).
Here is a Data Model, where I have listed the Predicates. I have chosen that example because it shows the Existential, etc, Predicates, as well as the Relationship ones, the only Predicates not listed are the Descriptors. Here, due to the seeker’s learning level, I am treating him as an user.
Therefore the event of more than one child table between two parent tables is not a problem, just name them as the Existential Fact re their content, and normalise the names.
The rules I gave for Verb Phrases for relationship names for Associative Tables come into play here. Here is a Predicate vs Table discussion, covering all points mentioned, in summary.
For a good short description re the proper use of Predicates and how to use them (which is quite a different context to that of responding to comments here), visit this answer, and scroll down to the Predicate section.
Ok, that is what we call a Key or NextKey table. Name it as such. If you have SubjectAreas, use COM_NextKey to indicate it is common across the database.
Btw, that is a very poor method of generating keys. Not scalable at all, but then with Oracle’s performance, it is probably "just fine". Further, it indicates that your database is full of surrogates, not relational in those areas. Which means extremely poor performance and lack of integrity.